在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

一致性哈希算法簡(jiǎn)介

算法與數(shù)據(jù)結(jié)構(gòu) ? 來(lái)源:labuladong ? 2023-04-04 11:53 ? 次閱讀

最近有一位讀者跟我交流,說(shuō)除了算法題之外,系統(tǒng)設(shè)計(jì)題是一大痛點(diǎn)。算法題起碼有很多刷題平臺(tái)可以動(dòng)手實(shí)踐,但系統(tǒng)設(shè)計(jì)類的題目一般很難實(shí)踐,所以看一些教程總結(jié)也只是一知半解,遇到讓寫(xiě)代碼實(shí)現(xiàn)系統(tǒng)的就懵了。

比如他最近被問(wèn)到一個(gè)大型爬蟲(chóng)系統(tǒng)的設(shè)計(jì)題,讓手寫(xiě)一致性哈希算法,加上一系列 follow up,就被難住了。

說(shuō)實(shí)話這個(gè)算法的實(shí)現(xiàn)并不難,所以本文就結(jié)合一致性哈希算法在工程中的應(yīng)用場(chǎng)景介紹一下這個(gè)算法算法,并給出代碼實(shí)現(xiàn),避免大家重蹈覆轍。

一致性哈希算法簡(jiǎn)介

這個(gè)名詞大家肯定不陌生,應(yīng)該也大概理解這個(gè)算法的邏輯,不過(guò)我這里還是要再介紹一下。

一致性哈希主要解決把數(shù)據(jù)平均分配到多個(gè)節(jié)點(diǎn)上的問(wèn)題,并且某些節(jié)點(diǎn)上線/下線后依然能夠做到自動(dòng)負(fù)載均衡。

其原理就是抽象出一個(gè)哈希環(huán),把服務(wù)器節(jié)點(diǎn)的 id 通過(guò)哈希函數(shù)映射到這個(gè)哈希環(huán)上:

ca0e0d10-d298-11ed-bfe3-dac502259ad0.jpg

同時(shí),把需要處理的數(shù)據(jù)也通過(guò)哈希函數(shù)映射到這個(gè)哈希環(huán)上,然后順時(shí)針找,遇到的第一個(gè)服務(wù)器節(jié)點(diǎn)來(lái)負(fù)責(zé)處理這個(gè)數(shù)據(jù):

ca202ab8-d298-11ed-bfe3-dac502259ad0.jpg

這樣一來(lái),我們其實(shí)已經(jīng)提供了一種機(jī)制將若干數(shù)據(jù)分布在若干服務(wù)節(jié)點(diǎn)上了,不妨稱它為 V1 版本的一致性哈希算法。

但 V1 版本的算法還有問(wèn)題:負(fù)載分布很可能不均衡。由于哈希函數(shù)的結(jié)果是難以預(yù)測(cè)的,所以可能出現(xiàn)這種情況:

ca2baf28-d298-11ed-bfe3-dac502259ad0.jpg

即某些服務(wù)器節(jié)點(diǎn)要負(fù)責(zé)的哈希環(huán)很長(zhǎng),而其他服務(wù)器負(fù)責(zé)的哈希環(huán)很短。這就會(huì)導(dǎo)致某些服務(wù)器負(fù)載很高,而其他的服務(wù)器負(fù)載很低,很不均衡。

而且,當(dāng)某個(gè)服務(wù)器節(jié)點(diǎn)下線后,它的負(fù)載會(huì)順時(shí)針轉(zhuǎn)移到下一個(gè)節(jié)點(diǎn)上,那么某些特定的節(jié)點(diǎn)下線順序很可能導(dǎo)致某些服務(wù)器節(jié)點(diǎn)負(fù)責(zé)的哈希環(huán)不斷加長(zhǎng),負(fù)載不斷增加。專業(yè)點(diǎn)說(shuō),這就是「數(shù)據(jù)傾斜」。

如何解決數(shù)據(jù)傾斜的問(wèn)題呢?可以給每個(gè)服務(wù)器節(jié)點(diǎn)添加若干「虛擬節(jié)點(diǎn)」分布在哈希環(huán)上,我們不妨稱其為 V2 版的一致性哈希算法:

ca39e728-d298-11ed-bfe3-dac502259ad0.jpg

上圖給每個(gè) Node 設(shè)置了 4 個(gè)虛擬節(jié)點(diǎn),這樣一來(lái),由于哈希函數(shù)的隨機(jī)性,每個(gè)服務(wù)器節(jié)點(diǎn)的虛擬節(jié)點(diǎn)能夠平均分布在哈希環(huán)上,那么數(shù)據(jù)就能夠比較均勻地分配到所有服務(wù)器節(jié)點(diǎn)上。

如果某個(gè)服務(wù)器節(jié)點(diǎn)下線,那么該服務(wù)器節(jié)點(diǎn)的所有虛擬節(jié)點(diǎn)都會(huì)從哈希環(huán)上摘除,它們的負(fù)載會(huì)遷移到順時(shí)針的下一個(gè)服務(wù)器節(jié)點(diǎn)上。

和 V1 版算法不同的是,因?yàn)樘摂M節(jié)點(diǎn)有多個(gè),它們的下一位不太可能是同一臺(tái)服務(wù)器的虛擬節(jié)點(diǎn),所以它們的負(fù)載大概率會(huì)均分到多臺(tái)服務(wù)器的虛擬節(jié)點(diǎn)上。

綜上,V2 版算法通過(guò)虛擬節(jié)點(diǎn)的方式完美解決了數(shù)據(jù)傾斜的問(wèn)題,是不是很巧妙?不過(guò)俗話說(shuō),紙上得來(lái)終覺(jué)淺,絕知此事要躬行,我們需要實(shí)踐才能真正寫(xiě)出正確的一致性哈希算法。

比方說(shuō),應(yīng)該用什么數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)哈希環(huán)?如果哈希函數(shù)出現(xiàn)哈希沖突怎么辦?真正寫(xiě)代碼的時(shí)候,這些細(xì)節(jié)問(wèn)題都是要考慮的。

下面我們就結(jié)合代碼和實(shí)際場(chǎng)景來(lái)看看一致性哈希算法的真實(shí)應(yīng)用

實(shí)際場(chǎng)景分析

就以消息隊(duì)列的消費(fèi)模型為例吧,我在前文用消息隊(duì)列做一個(gè)聯(lián)機(jī)游戲介紹過(guò) Apache Pulsar 的消費(fèi)模型,Pulsar 通過(guò) subscription 的抽象提供多種訂閱模式,其中 key_shared 模式比較有意思:

每條消息會(huì)有一個(gè) key,Pulsar 可以根據(jù)這個(gè) key 分發(fā)消息,保證帶有相同 key 的消息分發(fā)到同一個(gè)消費(fèi)者上。

官網(wǎng)的這幅圖比較好理解,圖中的K就是指消息的 key,V就是指消息的數(shù)據(jù):

ca532dfa-d298-11ed-bfe3-dac502259ad0.png

通過(guò)某些算法,所有的消息都會(huì)有消費(fèi)者去處理,比如上圖就是consumerA負(fù)責(zé)處理key=K3的消息,consumerB負(fù)責(zé)處理key=K1的消息,consumerC負(fù)責(zé)處理key=K2的消息。

當(dāng)然,如果有 consumer 加入或者離開(kāi),消息的分配會(huì)重置。比如consumerA下線,那么key=K3的消息會(huì)被分配給其他消費(fèi)者消費(fèi);如果有新的消費(fèi)者consumerD加入,那么當(dāng)前的分配方案也可能會(huì)改變。

簡(jiǎn)單總結(jié)就是:

1、在沒(méi)有 consumer 加入或者離開(kāi)的前提下,保證 key 相同的消息都會(huì)分配到固定的 consumer,不能一會(huì)兒分配到consumerA,一會(huì)兒分配給consumerB。

2、如果有 consumer 加入或者離開(kāi),可以重新進(jìn)行分配每個(gè) consumer 負(fù)責(zé)的 key,要求盡量把 key 平均分配給 consumer,避免出現(xiàn)某些 consumer 負(fù)責(zé)過(guò)多 key 的情況導(dǎo)致數(shù)據(jù)傾斜。

3、以上兩個(gè)操作,尤其是給 consumer 重新分配 key 的操作,效率要盡可能高。

對(duì)于上述場(chǎng)景,你如何設(shè)計(jì)分配算法,把這些帶有 key 的消息高效地、均勻地分配給所有 consumer 呢

我們來(lái)看看 Pulsar 是如何做的,官網(wǎng)對(duì)這部分的實(shí)現(xiàn)原理描述的比較清楚,參考鏈接如下:

https://pulsar.apache.org/docs/next/concepts-messaging/#key_shared

結(jié)合我之前在學(xué)習(xí)開(kāi)源項(xiàng)目的套路中介紹的查看源碼背景信息的技巧,可以發(fā)現(xiàn) Pulsar 的 key_shared 模式的消費(fèi)者實(shí)現(xiàn)其實(shí)是經(jīng)歷了一些演進(jìn)的。

最開(kāi)始的默認(rèn)實(shí)現(xiàn)方式叫做 Auto-split Hash Range,即抽象出來(lái)一個(gè)[0, 65535]的哈希區(qū)間,讓每個(gè) consumer 負(fù)責(zé)這個(gè)區(qū)間的一部分。比如有C1~C44 個(gè) consumer,那么它們會(huì)平分整個(gè)哈希區(qū)間:

016,38432,76849,15265,536
|-------C3------|-------C2------|-------C4------|-------C1------|

然后我們可以對(duì)每條消息的 key 計(jì)算哈希值并求模映射到[0, 65535]的區(qū)間中,這樣我們就可以選出負(fù)責(zé)處理這條消息的 consumer 了,而且 key 相同的消息總會(huì)分配到這個(gè) consumer 上。

那么如果有 consumer 上線或者下線怎么處理呢?

如果有 consumer 下線,那么它負(fù)責(zé)的哈希區(qū)間會(huì)直接交給右側(cè)的 consumer。比如上例中C4下線,那么哈希區(qū)間就會(huì)變成這樣:

016,38432,76865,536
|-------C3------|-------C2------|----------------C1---------------|

當(dāng)然這里也有個(gè)特殊情況,就是下線的那個(gè) consumer 右邊沒(méi)有其他 consumer 的情況,我們可以讓它左邊的 consumer 頂上來(lái)。比如現(xiàn)在的C1下線,那么就讓左邊的C2負(fù)責(zé)C1的區(qū)間:

016,38465,536
|-------C3------|--------------------------C2-----------------------|

如果有 consumer 上線,那么算法可以把最長(zhǎng)的哈希區(qū)間平分,分一半給新來(lái)的 consumer。比如此時(shí)C5上線,我們就可以把C2負(fù)責(zé)的一半哈希區(qū)間分給C5:

016,38440,96065,536
|-------C3------|-----------C5-----------|----------C2----------|

這就是 Auto-split Hash Range 的方案,不算復(fù)雜,具體的實(shí)現(xiàn)可以看 Pulsar 源碼中HashRangeAutoSplitStickyKeyConsumerSelector這個(gè)類,我在這里就不列舉了。

這個(gè)方案的問(wèn)題主要還是數(shù)據(jù)傾斜,比如上面的例子出現(xiàn)的這種情況,C2的負(fù)載顯然比C3多很多:

016,38465,536
|-------C3------|--------------------------C2-----------------------|

按照這個(gè)算法邏輯,一些 consumer 下線后很容易產(chǎn)生這種數(shù)據(jù)傾斜的情況,所以這個(gè)解決方案并不能均勻地把 key 分配給 consumer

那么如何優(yōu)化這個(gè)算法呢?就要用到一致性哈希算法了。

一致性哈希算法的實(shí)現(xiàn)

結(jié)合我在本文開(kāi)頭對(duì)一致性哈希算法的介紹,應(yīng)該很容易想到優(yōu)化思路。其實(shí)現(xiàn)在 Pulsar 就是使用一致性哈希算法來(lái)實(shí)現(xiàn)的 key_shared 訂閱。

首先抽象出一個(gè)值在[0, MAX_INT]的哈希環(huán),然后給每個(gè) consumer 分配 100 個(gè)虛擬節(jié)點(diǎn)映射到這個(gè)哈希環(huán)上。接下來(lái),我們把 key 的哈希值放在哈希環(huán)上,順時(shí)針?lè)较蛘业阶罱?consumer 虛擬節(jié)點(diǎn),也就找到了負(fù)責(zé)處理這個(gè) key 的 consumer。

哈希環(huán)我們一般用 TreeMap 實(shí)現(xiàn),直接看 Pulsar 源碼中ConsistentHashingStickyKeyConsumerSelector的實(shí)現(xiàn)吧,我提取了其中的關(guān)鍵邏輯并添加了詳細(xì)的注釋:

classConsistentHashingStickyKeyConsumerSelector{
//哈希環(huán),虛擬節(jié)點(diǎn)的哈希值->consumer列表
//因?yàn)榇嬖诠_突,多個(gè)虛擬節(jié)點(diǎn)可能映射到同一個(gè)哈希值,所以值為L(zhǎng)ist類型
NavigableMap>hashRing=newTreeMap<>();
//每個(gè)consumer有100個(gè)虛擬節(jié)點(diǎn)
intnumberOfPoints=100;

//將該consumer的100個(gè)虛擬節(jié)點(diǎn)添加到哈希環(huán)上
publicvoidaddConsumer(Consumerconsumer){
for(inti=0;i());
hashRing.get(hash).add(consumer);
}
}

//在哈希環(huán)上刪除該consumer的所有虛擬節(jié)點(diǎn)
publicvoidremoveConsumer(Consumerconsumer){
for(inti=0;i>ceilingEntry=hashRing.ceilingEntry(hash);
ListconsumerList;
if(ceilingEntry!=null){
consumerList=ceilingEntry.getValue();
}else{
//哈希環(huán)順時(shí)針轉(zhuǎn)一圈,回到開(kāi)頭尋找第一個(gè)節(jié)點(diǎn)
consumerList=hashRing.firstEntry().getValue();
}
//保證相同的key都會(huì)分配到同一個(gè)consumer
returnconsumerList.get(hash%consumerList.size());
}
}

當(dāng)消息被發(fā)送過(guò)來(lái)后,Pulsar 可以通過(guò)select方法選擇對(duì)應(yīng)的 consumer 來(lái)處理數(shù)據(jù);當(dāng)新的 consumer 上線時(shí),可以通過(guò)addConsumer將它的虛擬節(jié)點(diǎn)放到哈希環(huán)上并開(kāi)始接收消息;當(dāng)有 consumer 下線時(shí),可以通過(guò)removeConsumer將它的虛擬節(jié)點(diǎn)從哈希環(huán)上摘除,由其他 consumer 承擔(dān)它的工作。

因?yàn)槊總€(gè) consumer 有 100 個(gè)虛擬節(jié)點(diǎn),所以在 consumer 下線時(shí),負(fù)載其實(shí)是均勻地分配給了其他 consumer,因此一致性哈希算法能夠解決之前 Auto-split Hash Range 方案數(shù)據(jù)傾斜的問(wèn)題。




審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 虛擬機(jī)
    +關(guān)注

    關(guān)注

    1

    文章

    964

    瀏覽量

    29155
  • 哈希算法
    +關(guān)注

    關(guān)注

    1

    文章

    56

    瀏覽量

    10936

原文標(biāo)題:一致性哈希算法設(shè)計(jì)題,栽了

文章出處:【微信號(hào):TheAlgorithm,微信公眾號(hào):算法與數(shù)據(jù)結(jié)構(gòu)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    順序一致性和TSO一致性分別是什么?SC和TSO到底哪個(gè)好?

    內(nèi)存一致性之順序一致性(sequential consistency)可以說(shuō),最直觀的內(nèi)存一致性模型是sequentially consistent(SC):內(nèi)存訪問(wèn)執(zhí)行的順序與程序指定的順序相同
    發(fā)表于 07-19 14:54

    一致性規(guī)劃研究

    針對(duì)一致性規(guī)劃的高度求解復(fù)雜度,分析主流一致性規(guī)劃器的求解策略,給出影響一致性規(guī)劃器性能的主要因素:?jiǎn)l(fā)信息的有效,信念狀態(tài)表示方法的緊湊
    發(fā)表于 04-06 08:43 ?12次下載

    CMP中Cache一致性協(xié)議的驗(yàn)證

    CMP是處理器體系結(jié)構(gòu)發(fā)展的個(gè)重要方向,其中Cache一致性問(wèn)題的驗(yàn)證是CMP設(shè)計(jì)中的項(xiàng)重要課題。基于MESI一致性協(xié)議,本文建立了CMP的Cache
    發(fā)表于 07-20 14:18 ?38次下載

    加速器一致性接口

    Zynq PS上的加速器一致性接口(Accelerator Coherency Port, ACP)是個(gè)兼容AXI3的64位從機(jī)接口,連接到SCU(Snoop Control Unit),為PL
    發(fā)表于 11-17 15:04 ?3987次閱讀

    分布式一致性算法Yac

    傳統(tǒng)靜態(tài)拓?fù)渲鲝哪P头植际?b class='flag-5'>一致性算法存在嚴(yán)重負(fù)載不均及單點(diǎn)性能瓶頸效應(yīng),且崩潰節(jié)點(diǎn)大于集群規(guī)模的50qo時(shí)算法無(wú)法正常工作。針對(duì)上述問(wèn)題,提出基于動(dòng)態(tài)拓?fù)浼坝邢薇頉Q思想的分布式一致性
    發(fā)表于 11-27 17:49 ?0次下載
    分布式<b class='flag-5'>一致性</b><b class='flag-5'>算法</b>Yac

    基于軌跡標(biāo)簽的謠言一致性維護(hù)算法

    針對(duì)發(fā)布/訂閱系統(tǒng)中緩存副本一致性維護(hù)問(wèn)題,首先,對(duì)原有基于謠言的一致性維護(hù)算法進(jìn)行改進(jìn),提出種基于軌跡標(biāo)簽的謠言一致性維護(hù)
    發(fā)表于 12-17 11:35 ?0次下載
    基于軌跡標(biāo)簽的謠言<b class='flag-5'>一致性</b>維護(hù)<b class='flag-5'>算法</b>

    Cache一致性協(xié)議優(yōu)化研究

    問(wèn)題的由來(lái).總結(jié)了多核時(shí)代高速緩存一致性協(xié)議設(shè)計(jì)的關(guān)鍵問(wèn)題,綜述了近年來(lái)學(xué)術(shù)界對(duì)一致性的研究.從程序訪存行為模式、目錄組織結(jié)構(gòu)、一致性粒度、一致性協(xié)議流量、目錄協(xié)議的可擴(kuò)展性等方面,闡
    發(fā)表于 12-30 15:04 ?0次下載
    Cache<b class='flag-5'>一致性</b>協(xié)議優(yōu)化研究

    優(yōu)化模型的乘偏好關(guān)系一致性改進(jìn)

    針對(duì)乘偏好信息下的決策問(wèn)題,引入乘偏好關(guān)系的有序一致性、滿意一致性以及一致性指數(shù)等概念,建立以偏差變量最小化為目標(biāo)函數(shù)的優(yōu)化模型,進(jìn)而構(gòu)
    發(fā)表于 03-20 17:28 ?0次下載

    一致性哈希是什么?為什么它是可擴(kuò)展的分布式系統(tǒng)架構(gòu)的個(gè)必要工具

    在本文中,我們將了解一致性哈希是什么、為什么它是可擴(kuò)展的分布式系統(tǒng)架構(gòu)中的個(gè)必要工具。
    的頭像 發(fā)表于 07-17 17:57 ?4590次閱讀

    哈希圖一致性算法已被驗(yàn)證為異步拜占庭容錯(cuò)

    HederaHashgraph在下代公共分類帳中擁有多樣化的治理。它最近宣布哈希圖一致性算法已被驗(yàn)證為異步拜占庭容錯(cuò)。這是通過(guò)使用Coq系統(tǒng)的計(jì)算機(jī)檢查的數(shù)學(xué)證明完成的。
    發(fā)表于 10-23 11:07 ?1944次閱讀

    基于改進(jìn)一致性的多無(wú)人機(jī)編隊(duì)控制算法

    基于改進(jìn)一致性的多無(wú)人機(jī)編隊(duì)控制算法
    發(fā)表于 06-22 16:02 ?16次下載

    Dubbo負(fù)載均衡策略之一致性哈希

    本文主要講解了一致性哈希算法的原理以及其存在的數(shù)據(jù)傾斜的問(wèn)題,然后引出解決數(shù)據(jù)傾斜問(wèn)題的方法,最后分析一致性哈希
    的頭像 發(fā)表于 06-16 15:30 ?1227次閱讀
    Dubbo負(fù)載均衡策略之<b class='flag-5'>一致性</b><b class='flag-5'>哈希</b>

    如何保證緩存一致性

    “ 本文的參考文章是2022年HOT 34上Intel Rob Blakenship關(guān)于CXL緩存一致性篇介紹。”
    的頭像 發(fā)表于 10-19 17:42 ?1580次閱讀
    如何保證緩存<b class='flag-5'>一致性</b>

    DDR一致性測(cè)試的操作步驟

    DDR一致性測(cè)試的操作步驟? DDR(雙數(shù)據(jù)率)一致性測(cè)試是對(duì)DDR內(nèi)存模塊進(jìn)行測(cè)試以確保其性能和可靠。在進(jìn)行DDR一致性測(cè)試時(shí),需要遵循
    的頭像 發(fā)表于 02-01 16:24 ?2497次閱讀

    深入理解數(shù)據(jù)備份的關(guān)鍵原則:應(yīng)用一致性與崩潰一致性的區(qū)別

    深入理解數(shù)據(jù)備份的關(guān)鍵原則:應(yīng)用一致性與崩潰一致性的區(qū)別 在數(shù)字化時(shí)代,數(shù)據(jù)備份成為了企業(yè)信息安全的核心環(huán)節(jié)。但在備份過(guò)程中,兩個(gè)關(guān)鍵概念——應(yīng)用一致性和崩潰一致性,常常被誤解或混淆。
    的頭像 發(fā)表于 03-11 11:29 ?1347次閱讀
    深入理解數(shù)據(jù)備份的關(guān)鍵原則:應(yīng)用<b class='flag-5'>一致性</b>與崩潰<b class='flag-5'>一致性</b>的區(qū)別
    主站蜘蛛池模板: 国产91色综合久久免费分享 | 伊人久久大香线蕉综合影 | 加勒比黑人喝羽月希奶水 | 宅男午夜 | 国产女人在线观看 | 国产二区三区毛片 | 精品国产一区二区三区国产馆 | 美女免费视频一区二区三区 | 国产视频精品久久 | 7777sq国产精品 | 亚洲综合情| 成人国内精品久久久久影院 | 五月天婷婷社区 | 成人国产日本亚洲精品 | 成人a毛片高清视频 | 亚洲图片综合区另类图片 | 看片地址| vip免费观看| 日本色频| 免费一级毛片在线播放 | 在线午夜视频 | 99 久久99久久精品免观看 | 久久天天躁狠狠躁夜夜躁综合 | 国产国拍亚洲精品mv在线观看 | 免费在线观看黄色 | 伊人精品在线观看 | 在线国产播放 | 亚洲综合天堂网 | 欧美三级黄视频 | 久青草国产观看在线视频 | 亚洲a毛片| 97久久综合九色综合 | 婷婷精品视频 | 日韩国产片 | 好紧好爽太大了h快穿 | 国产精品嫩草影院一二三区入口 | 伊人蕉久| 在线最新版www资源网 | 亚洲一区二区免费在线观看 | 夜夜夜操操操 | 美女扒开内裤无遮挡禁18 |