<kbd id="5sdj3"></kbd>
<th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>

    Elasticseatch筆記(基礎篇)

    共 11368字,需瀏覽 23分鐘

     ·

    2021-01-23 19:24


    本文公眾號來源:Echo1024

    作者:我白日夢

    本文已收錄至我的GitHub


    【對線面試官】系列?一周兩篇持續(xù)更新中!

    1.1、認識ES

    關系型數(shù)據(jù)庫:

    像MySQL這種數(shù)據(jù)庫就是傳統(tǒng)的關系型數(shù)據(jù)庫。它有個很直觀的特點:每一張數(shù)據(jù)表的列在創(chuàng)建表的時候就需要確定下來。比如你創(chuàng)建一個user表,定義了3列id、username、password。這時如果你的實體類中多了一個age的字段,那這個實體是不能保存進user表的。(當然后續(xù)你可以通過DDL修改添加列或者減少列。讓實體類的屬性和表中的列一一對應)。

    非關系型數(shù)據(jù)庫:

    非關系型數(shù)據(jù)庫也就是我們常聽說的NoSQL。常見的有:MongoDB、Redis、Elasticsearch。

    且不說性能方面,單說使用方面NoSQL這種非關系類型的數(shù)據(jù)庫都支持你往它里面存儲一個json對象,這個json有多少個字段并不是它關系的,拿上面的例子來說,只要你給他一個對象,不管有沒有age、它都能幫你存儲進去。

    關于ES更多的知識點我們在下文中展開,再說一下ES常見的使用場景和特性:

    站內(nèi)搜索:

    如果你的公司想做自己的站內(nèi)搜索,那ES再合適不過了。作為非關系型數(shù)據(jù)庫的ES允許你往它里面存儲各種格式不確定的Json對象,還為你提供了全文本搜索和分析引擎。它使您可以快速,近乎實時地(1 s)存儲,搜索和分析大量數(shù)據(jù)。一個字:快!

    日志采集系統(tǒng):

    Elasticsearch是Elastic公司的核技術,并且Elastic公司還有其他諸如:Logstash、Filebeat、Kibana等技術棧。常見的公司里面使用的日志管理系統(tǒng)就可以使用ELK+Filebeat搭建起來,F(xiàn)ilebeat收集日志推送到Logstash做處理,然后Logstash將數(shù)據(jù)存儲入ES,最終通過Kibana展示日志。

    可擴展性:

    Elasticsearch天生就是分布式的,既能以單機的形式運行一臺性能很差的服務器上。它也可以形成一個成百上千節(jié)點的集群。并且它自己會管理集群中的節(jié)點,在ES中我們可以隨意的添加、摘除節(jié)點,集群自己會將數(shù)據(jù)均攤在各個節(jié)點上。

    1.2、安裝、啟動ES、Kibana、IK分詞器

    1. 安裝很簡單,所以詳細過程不會寫到文章中。
    2. 安裝啟動教程、ES、Kibana、IK分詞器安裝包都以百度網(wǎng)盤的方式分享給大家,后臺回復:es 可領取

    二、核心概念

    因為這是第一篇基礎篇,對小白友好一些,所以需要先了解一些基本概念,你可以耐折性子讀一下,都不難理解的哈。

    2.1、Near Realtime (NRT)

    ES號稱對外提供的是近實時的搜索服務,意思是數(shù)據(jù)從寫入ES到可以被Searchable僅僅需要1秒鐘,所以說基于ES執(zhí)行的搜索和分析可以達到秒級。

    2.2、Cluster

    集群:集群是一個或多個node的集合,它們一起保存你存放進去的數(shù)據(jù),用戶可以在所有的node之間進行檢索,一般的每個集群都會有一個唯一的名稱標識,默認的名稱標識為 elasticsearch ,這個名字很重要,因為node想加入cluster時,需要這個名稱信息。

    確保別在不同的環(huán)境中使用相同的集群名稱,進而避免node加錯集群的情況,一顆考慮下面的集群命名風格logging-stagelogging-devlogging-pro

    2.3、Node

    單臺server就是一個node,它和cluster一樣,也存在一個默認的名稱。但是它的名稱是通過UUID生成的隨機串,當然用戶也可以定制不同的名稱,但是這個名字最好別重復。這個名稱對于管理來說很在乎要,因為需要確定,當前網(wǎng)絡中的哪臺服務器,對應這個集群中的哪個節(jié)點。

    node存在一個默認的設置,默認的,當每一個node在啟動時都會自動的去加入一個叫elasticsearch的節(jié)點,這就意味著,如果用戶在網(wǎng)絡中啟動了多個node,它們會彼此發(fā)現(xiàn),然后組成集群。

    在單個的cluster中,你可以擁有任意多的node。假如說你的網(wǎng)絡上沒有其它正在運行的節(jié)點,然后你啟動一個新的節(jié)點,這個新的節(jié)點自己會組建一個集群。

    2.4、Index

    index是一類擁有相似屬性的document的集合。比如你可以為消費者的數(shù)據(jù)創(chuàng)建一個index,為產(chǎn)品創(chuàng)建一個index,為訂單創(chuàng)建一個index。

    index名稱(必須是小寫的字符)。?當需要對index中的文檔執(zhí)行索引、搜索、更新、刪除、等操作時,都需要用到這個index。

    理論上:你可以在一個集群中創(chuàng)建任意數(shù)量的index。

    2.5、Type

    Type可以作為index中的邏輯類別。為了更細的劃分,比如用戶數(shù)據(jù)type、評論數(shù)據(jù)type、博客數(shù)據(jù)type

    在設計時盡最大努力讓擁有更多相同field的document劃分到同一個type下。

    2.6、Document

    document就是ES中存儲的一條數(shù)據(jù),就像mysql中的一行記錄一樣。它可以是一條用戶的記錄、一個商品的記錄等等

    2.7、一個不嚴謹?shù)男〗Y(jié):

    為什么說這是不嚴謹?shù)男〗Y(jié)呢? 就是說下面三個對應關系只能說的從表面上看起來比較相似。但是ES中的type其實是一個邏輯上的劃分。數(shù)據(jù)在存儲是時候依然是混在一起存儲的(往下看下文中有寫),而mysql中的不同表的兩個列是絕對沒有關系的。

    Elasticsearch關系型數(shù)據(jù)庫
    Document
    type
    index數(shù)據(jù)庫

    2.8、Shards & Replicas

    2.8.1、問題引入:

    如果讓一個Index自己存儲1TB的數(shù)據(jù),響應的速度就會下降。為了解決這個問題,ES提供了一種將用戶的Index進行subdivide的騷操作,就是將index分片,每一片都叫一個Shards,進而實現(xiàn)了將整體龐大的數(shù)據(jù)分布在不同的服務器上存儲。

    2.8.2、什么是shard?

    shard分成replica shard和primary shard。顧名思義一個是主shard、一個是備份shard, 負責容錯以及承擔部分讀請求。

    shard可以理解成是ES中最小的工作單元。所有shard中的數(shù)據(jù)之和,才是整個ES中存儲的數(shù)據(jù)。可以把shard理解成是一個luncene的實現(xiàn),擁有完整的創(chuàng)建索引,處理請求的能力。

    下圖是兩個node,6個shard的組成的集群的劃分情況:

    兩個節(jié)點的分布情況

    你可以看一下上面的圖,圖中無論java應用程序訪問的是node1還是node2,其實都能獲取到數(shù)據(jù)。

    2.8.3、shard的默認數(shù)量

    新創(chuàng)建的節(jié)點會存在5個primary shard,注意!后續(xù)不然能再改動primary shard的值,如果每一個primary shard都對應一個replica shard,按理說單臺es啟動就會存在10個分片,但是現(xiàn)實是,同一個節(jié)點的replica shard和primary shard不能存在于一個server中,因此單臺es默認啟動后的分片數(shù)量還是5個。

    2.8.4、如何拓容Cluster

    首先明確一點:一旦index創(chuàng)建完成了,primary shard的數(shù)量就不可能再發(fā)生變化。

    因此橫向拓展就得添加replica的數(shù)量, 因為replica shard的數(shù)量后續(xù)是可以改動的。也就是說,如果后續(xù)我們將它的數(shù)量改成了2, 就意味著讓每個primary shard都擁有了兩個replica shard, 計算一下: 5+5*2=15 集群就會拓展成15個節(jié)點。

    如果想讓每一個shard都有最多的系統(tǒng)的資源就增加服務器的數(shù)量,讓每一個shard獨占一個服務器。

    2.8.5、舉個例子:

    shard和replica入門圖

    上圖中存在上下兩個node,每個node中都有一個 自己的primary shard其它節(jié)點的replica shard,為什么是強調(diào)自己和其它呢? 因為ES中規(guī)定,同一個節(jié)點的replica shard和primary shard不能存在于一個server中,而不同節(jié)點的primary shard可以存在于同一個server上。

    當primary shard宕機時,因為它對應的replicas shard在其它的server沒有受到影響,所以ES可以繼續(xù)響應用戶的讀請求。通過這種分片的機制,并且分片的地位相當,假設單個shard可以處理2000/s的請求,通過橫向拓展可以在此基礎上成倍提升系統(tǒng)的吞吐量,天生分布式,高可用。

    此外: 每一個document肯定存在于一個primary shard和這個primary shard 對應的replica shard中, 絕對不會出現(xiàn)同一個document同時存在于多個primary shard中的情況。

    三、入門探索:

    下面的小節(jié)中你會看到我使用大量的GET / POST 等等包括什么query。其實你不用詫異為啥整一堆這些東西而不寫點代碼。

    其實這些命令對于ES來說,就像是SQL和MySQL的關系。換句話說,其實你寫的代碼的底層幫你執(zhí)行的也是我下面說得的這些命令。所以,別怕麻煩,下面的這些知識點無論如何你都不能直接跨越過去。

    3.1、集群的健康狀況

    GET /_cat/health?v

    執(zhí)行結(jié)果如下:

    epoch??????timestamp?cluster???????status?node.total?node.data?shards?pri?relo?init?unassign?pending_tasks?max_task_wait_time?active_shards_percent
    1572595632?16:07:12??elasticsearch?yellow??????????1?????????1??????5???5????0????0????????5?????????????0??????????????????-?????????????????50.0%

    解讀上面的信息,默認的集群名是elasticsearch,當前集群的status是yellow,后續(xù)列出來的是集群的分片信息,最后一個active_shards_percent表示當前集群中僅有一半shard是可用的。

    狀態(tài):

    存在三種狀態(tài)分別是:red、green、yellow

    • green : 表示當前集群所有的節(jié)點全部可用。
    • yellow: 表示ES中所有的數(shù)據(jù)都是可以訪問的,但是并不是所有的replica shard都是可以使用的(我現(xiàn)在是默認啟動一個node,而ES又不允許同一個node的primary shard和replica shard共存,因此我當前的node中僅僅存在5個primary shard,為status為黃色)。
    • red: 集群宕機,數(shù)據(jù)不可訪問。

    3.2、集群的索引信息

    GET /_cat/indices?v

    結(jié)果:

    health?status?index??????????????uuid???????????????????pri?rep?docs.count?docs.deleted?store.size?pri.store.size
    yellow?open???ai_answer_question?cl_oJNRPRV-bdBBBLLL05g???5???1?????203459????????????0????172.3mb????????172.3mb

    顯示狀態(tài)為yellow,表示存在replica shard不可用, 存在5個primary shard,并且每一個primary shard都有一個replica shard , 一共20多萬條文檔,未刪除過文檔,文檔占用的空間情況為172.3兆。

    3.3、創(chuàng)建index

    PUT /customer?pretty

    ES 使用的RestfulAPI,新增使用put,這是個很親民的舉動。

    3.4、添加 or 修改

    如果是ES中沒有過下面的數(shù)據(jù)則添加進去,如果存在了id=1的元素就修改(全量替換)。

    • 格式:PUT /index/type/id

    全量替換時,原來的document是沒有被刪除的!而是被標記為deleted,被標記成的deleted是不會被檢索出來的,當ES中數(shù)據(jù)越來越多時,才會刪除它。

    PUT /customer/_doc/1?pretty
    {
    "name": "John Doe"
    }

    響應:

    {
    ??"_index":?"customer",
    ??"_type":?"_doc",
    ??"_id":?"1",
    ??"_version":?1,
    ??"result":?"created",
    ??"_shards":?{
    ????"total":?2
    ????"successful":?1,
    ????"failed":?0
    ??},
    ??"_seq_no":?0,
    ??"_primary_term":?1
    }

    強制創(chuàng)建,加添_create或者?op_type=create。

    PUT?/customer/_doc/1?op_type=create
    PUT?/customer/_doc/1/_create
    • 局部更新(Partial Update)

    不指定id則新增document

    POST?/customer/_doc?pretty
    {
    ??"name":?"Jane?Doe"
    }

    指定id則進行doc的局部更新操作

    POST /customer/_doc/1?pretty
    {
    "name": "Jane Doe"
    }

    并且POST相對于上面的PUT而言,不論是否存在相同內(nèi)容的doc,只要不指定id,都會使用一個隨機的串當成id,完成doc的插入。

    Partial Update先獲取document,再將傳遞過來的field更新進document的json中,將老的doc標記為deleted,再將創(chuàng)建document,相對于全量替換中間會省去兩次網(wǎng)絡請求

    3.5、檢索

    格式: GET /index/type/

    GET /customer/_doc/1?pretty

    響應:

    {
    ??"_index":?"customer"
    ??"_type":?"_doc",
    ??"_id":?"1",
    ??"_version":?1,
    ??"found":?true
    ??"_source":?{
    ????"name":?"John?Doe"
    ??}
    }

    3.6、刪除

    刪除一條document。

    大部分情況下,原來的document不會被立即刪除,而是被標記為deleted,被標記成的deleted是不會被檢索出來的,當ES中數(shù)據(jù)越來越多時,才會刪除它。

    DELETE /customer/_doc/1

    響應:

    {
    ??"_index":?"customer",
    ??"_type":?"_doc",
    ??"_id":?"1"
    ??"_version":?2,
    ??"result":?"deleted",
    ??"_shards":?{
    ????"total":?2,
    ????"successful":?1
    ????"failed":?0
    ??},
    ??"_seq_no":?1,
    ??"_primary_term":?1
    }

    刪除index

    DELETE /index1
    DELETE /index1,index2
    DELETE /index*
    DELETE /_all

    可以在elasticsearch.yml中將下面這個設置置為ture,表示禁止使用 DELETE /_all
    action.destructive_required_name:true

    響應

    {
    ??"acknowledged":?true
    }

    3.6、更新文檔

    上面說了POST關鍵字,可以實現(xiàn)不指定id就完成document的插入, POST + _update關鍵字可以實現(xiàn)更新的操作。

    POST?/customer/_doc/1/_update?pretty
    {
    ??"doc":?{?"name":?"changwu"?}
    }

    POST+_update進行更新的動作依然需要指定id, 但是相對于PUT來說,當使用POST進行更新時,id不存在的話會報錯,而PUT則會認為這是在新增。

    此外: 針對這種更新操作,ES會先刪除原來的doc,然后插入這個新的doc。

    四、document api

    4.1、search

    • 檢索所有索引下面的所有數(shù)據(jù)
    /_search
    • 搜索指定索引下的所有數(shù)據(jù)
    /index/_search
    • 更多模式
    /index1/index2/_search
    /*1/*2/_search
    /index1/index2/type1/type2/_search
    /_all/type1/type2/_search

    4.2、_mget api 批量查詢

    mget是ES為我們提供的批量查詢的API,我們只需要制定好 index、type、id。ES會將命中的記錄批量返回給我們。

    • 在docs中指定_index_type,_id
    GET?/_mget
    {
    ????"docs"?:?[
    ????????{
    ????????????"_index"?:?"test"
    ????????????"_type"?:?"_doc",
    ????????????"_id"?:?"1"
    ????????},
    ????????{
    ????????????"_index"?:?"test",
    ????????????"_type"?:?"_doc",
    ????????????"_id"?:?"2"
    ????????}
    ????]
    }
    • 在URL中指定index
    GET?/test/_mget
    {
    ????"docs"?:?[
    ????????{
    ????????????"_type"?:?"_doc"
    ????????????"_id"?:?"1"
    ????????},
    ????????{
    ????????????"_type"?:?"_doc"
    ????????????"_id"?:?"2"
    ????????}
    ????]
    }
    • 在URL中指定 index和type
    GET?/test/type/_mget
    {
    ????"docs"?:?[
    ????????{
    ????????????"_id"?:?"1"
    ????????},
    ????????{
    ????????????"_id"?:?"2"
    ????????}
    • 在URL中指定index和type,并使用ids指定id范圍
    GET?/test/type/_mget
    {
    ????"ids"?:?["1",?"2"]
    }
    • 為不同的doc指定不同的過濾規(guī)則
    GET?/_mget
    {
    ????"docs"?:?[
    ????????{
    ????????????"_index"?:?"test",
    ????????????"_type"?:?"_doc",
    ????????????"_id"?:?"1"
    ????????????"_source"?:?false
    ????????},
    ????????{
    ????????????"_index"?:?"test"
    ????????????"_type"?:?"_doc",
    ????????????"_id"?:?"2",
    ????????????"_source"?:?["field3",?"field4"]
    ????????},
    ????????{
    ????????????"_index"?:?"test",
    ????????????"_type"?:?"_doc",
    ????????????"_id"?:?"3",
    ????????????"_source"?:?{
    ????????????????"include":?["user"],
    ????????????????"exclude":?["user.location"]
    ????????????}
    ????????}
    ????]
    }

    4.3、_bulk api 批量增刪改

    4.3.1、基本語法

    {"action":{"metadata"}}\n
    {"data"}\n

    存在哪些類型的操作可以執(zhí)行呢?

    • delete: 刪除文檔。

    • create: _create 強制創(chuàng)建。

    • index: 表示普通的put操作,可以是創(chuàng)建文檔也可以是全量替換文檔。

    • update: 局部替換。

    上面的語法中并不是人們習慣閱讀的json格式,但是這種單行形式的json更具備高效的優(yōu)勢

    ES如何處理普通的json如下:

    • 將json數(shù)組轉(zhuǎn)換為JSONArray對象,這就意味著內(nèi)存中會出現(xiàn)一份一模一樣的拷貝,一份是json文本,一份是JSONArray對象。

    但是如果上面的單行JSON,ES直接進行切割使用,不會在內(nèi)存中整一個數(shù)據(jù)拷貝出來。

    4.3.2、delete

    delete比較好看僅僅需要一行json就ok

    {?"delete"?:?{?"_index"?:?"test",?"_type"?:?"_doc",?"_id"?:?"2"?}?}

    4.3.3、create

    兩行json,第一行指明我們要創(chuàng)建的json的index,type以及id

    第二行指明我們要創(chuàng)建的doc的數(shù)據(jù)

    {?"create"?:?{?"_index"?:?"test",?"_type"?:?"_doc",?"_id"?:?"3"?}?}
    {?"field1"?:?"value3"?}

    4.3.4、index

    相當于是PUT,可以實現(xiàn)新建或者是全量替換,同樣是兩行json。

    第一行表示將要新建或者是全量替換的json的index type 以及 id。

    第二行是具體的數(shù)據(jù)。

    {?"index"?:?{?"_index"?:?"test",?"_type"?:?"_doc",?"_id"?:?"1"?}?}
    {?"field1"?:?"value1"?}

    4.3.5、update

    表示 parcial update,局部替換。

    它可以指定一個retry_on_conflict的特性,表示可以重試3次。

    POST?_bulk
    {?"update"?:?{"_id"?:?"1",?"_type"?:?"_doc",?"_index"?:?"index1",?"retry_on_conflict"?:?3}?}
    {?"doc"?:?{"field"?:?"value"}?}
    {?"update"?:?{?"_id"?:?"0",?"_type"?:?"_doc",?"_index"?:?"index1",?"retry_on_conflict"?:?3}?}
    {?"script"?:?{?"source":?"ctx._source.counter?+=?params.param1",?"lang"?:?"painless",?"params"?:?{"param1"?:?1}},?"upsert"?:?{"counter"?:?1}}
    {?"update"?:?{"_id"?:?"2",?"_type"?:?"_doc",?"_index"?:?"index1",?"retry_on_conflict"?:?3}?}
    {?"doc"?:?{"field"?:?"value"},?"doc_as_upsert"?:?true?}
    {?"update"?:?{"_id"?:?"3",?"_type"?:?"_doc",?"_index"?:?"index1",?"_source"?:?true}?}
    {?"doc"?:?{"field"?:?"value"}?}
    {?"update"?:?{"_id"?:?"4",?"_type"?:?"_doc",?"_index"?:?"index1"}?}
    {?"doc"?:?{"field"?:?"value"},?"_source":?true}

    4.4、滾動查詢技術

    如果你想一次性查詢好幾萬條數(shù)據(jù),這么龐大的數(shù)據(jù)量,ES性能肯定會受到影響。這時可以選擇使用滾動查詢(scroll)。一批一批的查詢,直到所有的數(shù)據(jù)被查詢完成。也就是說它會先搜索一批數(shù)據(jù)再搜索一批數(shù)據(jù)。

    示例如下:每次發(fā)送一次scroll請求,我們還需要指定一個scroll需要的參數(shù):一個時間窗口,每次搜索只要在這個時間窗口內(nèi)完成就ok。

    GET?/index/type/_search?scroll=1m
    {
    ????"query":{
    ????????"match_all":{}
    ????},
    ????"sort":["_doc"],
    ????"size":3
    }

    響應

    {
    ??"_scroll_id":?"DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAACNFlJmWHZLTkFhU0plbzlHX01LU2VzUXcAAAAAAAAAkRZSZlh2S05BYVNKZW85R19NS1Nlc1F3AAAAAAAAAI8WUmZYdktOQWFTSmVvOUdfTUtTZXNRdwAAAAAAAACQFlJmWHZLTkFhU0plbzlHX01LU2VzUXcAAAAAAAAAjhZSZlh2S05BYVNKZW85R19NS1Nlc1F3",
    ??"took":?9
    ??"timed_out":?false,
    ??"_shards":?{
    ????"total":?5
    ????"successful":?5,
    ????"skipped":?0,
    ????"failed":?0
    ??},
    ??"hits":?{
    ????"total":?2,
    ????"max_score":?null,
    ????"hits":?[
    ??????{
    ????????"_index":?"my_index"
    ????????"_type":?"_doc",
    ????????"_id":?"2"
    ????????"_score":?null,
    ????????"_source":?{
    ??????????"title":?"This?is?another?document"
    ??????????"body":?"This?document?has?a?body"
    ????????},
    ????????"sort":?[
    ??????????0
    ????????]
    ??????},
    ??????{
    ????????"_index":?"my_index",
    ????????"_type":?"_doc",
    ????????"_id":?"1"
    ????????"_score":?null,
    ????????"_source":?{
    ??????????"title":?"This?is?a?document"
    ????????},
    ????????"sort":?[
    ??????????0
    ????????]
    ??????}
    ·????]
    ??}
    }

    查詢下一批數(shù)據(jù)時,需要攜帶上一次scroll返回給我們的_scroll_id再次滾動查詢

    GET?/_search/scroll
    {
    ????"scroll":"1m",
    ????"_scroll_id":?"DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAACNFlJmWHZLTkFhU0plbzlHX01LU2VzUXcAAAAAAAAAkRZSZlh2S05BYVNKZW85R19NS1Nlc1F3AAAAAAAAAI8WUmZYdktOQWFTSmVvOUdfTUtTZXNRdwAAAAAAAACQFlJmWHZLTkFhU0plbzlHX01LU2VzUXcAAAAAAAAAjhZSZlh2S05BYVNKZW85R19NS1Nlc1F3"
    }

    滾動查詢時,如果采用基于_doc的排序方式會獲得較高的性能。


    歡迎關注我的微信公眾號【面試造火箭】來聊聊Java面試

    添加我的私人微信sanwaiyihao進一步交流和學習

    【對線面試官】系列?一周兩篇持續(xù)更新中!

    瀏覽 66
    點贊
    評論
    收藏
    分享

    手機掃一掃分享

    分享
    舉報
    評論
    圖片
    表情
    推薦
    點贊
    評論
    收藏
    分享

    手機掃一掃分享

    分享
    舉報

    <kbd id="5sdj3"></kbd>
    <th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>
    最新版中文官网资源 | 黄片视频在线 | 色校园第一页 | 你懂的网址在线观看 | 巨乳无码噜噜噜久久久 |