<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          3萬字聊聊什么是Redis(六)

          共 5952字,需瀏覽 12分鐘

           ·

          2021-12-22 17:15

          大家好,我是Leo

          繼上篇Redis技術(shù)總結(jié)五,我們繼續(xù)聊聊Redis的相關(guān)技術(shù)!

          上一篇我們介紹了

          1. 緩沖區(qū)溢出調(diào)優(yōu)方案。
          2. 緩存類型,同步直寫,異步寫回策略。
          3. 緩存淘汰策略,LRU,LFU算法的實(shí)現(xiàn)。
          4. 臟緩存,干凈緩存的判斷依據(jù)

          這篇主要是介紹一下 緩存和數(shù)據(jù)庫不一致,緩存污染,基于SSD實(shí)現(xiàn)大容量,Redis解決大并發(fā),Redis實(shí)現(xiàn)分布式鎖。

          推薦閱讀

          3萬字聊聊什么是MySQL

          3萬字聊聊什么是Redis(一)

          3萬字聊聊什么是Redis(二)

          3萬字聊聊什么是Redis(三)

          3萬字聊聊什么是Redis(四)

          3萬字聊聊什么是Redis(五)

          緩存和數(shù)據(jù)一致性問題

          Redis的高頻面試:緩存和數(shù)據(jù)的一致性問題。今天我們整理總結(jié)一下。

          Redis的緩存分兩種類型,讀寫緩存,只讀緩存。不同的類型會(huì)產(chǎn)生不同的問題以及不同的解決方案,下面我們了解一下。

          讀寫緩存

          我們先來介紹一下什么是讀寫緩存。讀寫緩存就代表一個(gè)主庫一樣。既要提供寫服務(wù),也要提供讀服務(wù)。

          當(dāng)用戶選用讀寫緩存時(shí),如果對(duì)數(shù)據(jù)發(fā)生了修改。我們除了要考慮數(shù)據(jù)庫的一致性以外,還要考慮緩存中的數(shù)據(jù)一致性。正如我們前面所說,Redis的寫請(qǐng)求也是一個(gè)存儲(chǔ)介質(zhì)。所以我們在配置時(shí),要采取相應(yīng)的寫回策略

          • 當(dāng)采用同步直寫策略,寫緩存時(shí),可以保證緩存與數(shù)據(jù)庫的數(shù)據(jù)一致性。
          • 當(dāng)采用異步寫回策略,寫緩存時(shí),由于是異步執(zhí)行,無法保證命令都執(zhí)行也就是無法保證數(shù)據(jù)一致性。

          對(duì)于讀寫緩存來說,如果要保證數(shù)據(jù)一致性就盡量采用同步直寫策略。也就是同步執(zhí)行,程序中一定不要忘記加事務(wù)機(jī)制來保證數(shù)據(jù)庫和緩存的原子性。

          有些數(shù)據(jù)要求比較高的可以采用同步直寫,對(duì)要求不高的屬性來說(創(chuàng)建時(shí)間,來源地,家鄉(xiāng),屬性等)我們就可以采用異步寫回策略。

          只讀緩存

          介紹完讀寫緩存,我相信很多人對(duì)只讀緩存應(yīng)該能知道的差不多了。我再來整理總結(jié)一下。只讀緩存就代表從庫一樣,只負(fù)責(zé)讀服務(wù),不負(fù)責(zé)用戶的寫服務(wù)。

          所以平時(shí)我們在?新增數(shù)據(jù)?的時(shí)候就可以繞過Redis,直接寫入數(shù)據(jù)庫,這樣下次用戶訪問的時(shí)候發(fā)現(xiàn)緩存中沒有(緩存缺失)就會(huì)直接打到數(shù)據(jù)庫,在數(shù)據(jù)庫發(fā)現(xiàn)之后就會(huì)緩存下來插入到緩存中。緩存之后我們下次便可以在緩存中直接讀取就不需要再去查詢數(shù)據(jù)庫了。

          眾所周知,Redis的并發(fā)承受能力大于MySQL的并發(fā)承受能力。這也是我們?yōu)槭裁匆彺娴絉edis中的原因。

          如果是?刪除或修改操作?我們要更新數(shù)據(jù)庫的同時(shí),也要更新緩存。如果不刪除緩存的話就造成了原本這個(gè)用戶不存在,但是可以還是登錄進(jìn)去訪問,就造成了數(shù)據(jù)不一致問題。嚴(yán)重的話可能會(huì)導(dǎo)致系統(tǒng)級(jí)的報(bào)錯(cuò)!(比如關(guān)聯(lián)查詢時(shí),不存在數(shù)據(jù)error)

          所以Redis,MySQL都要保證原子性,

          • 先刪緩存,后更新數(shù)據(jù)庫:緩存刪除成功,數(shù)據(jù)更新失敗,導(dǎo)致用戶向緩存讀數(shù)據(jù)時(shí),沒有發(fā)現(xiàn)緩存key就會(huì)打向數(shù)據(jù)庫,而數(shù)據(jù)庫數(shù)據(jù)沒有更新成功導(dǎo)致讀到舊值
          • 先更新數(shù)據(jù)庫,后刪緩存:?更新數(shù)據(jù)庫成功時(shí),緩存刪除失敗,就會(huì)導(dǎo)致數(shù)據(jù)庫保留了最新的值,用戶向Redis讀數(shù)據(jù)時(shí),發(fā)現(xiàn)緩存key存在,直接返回了就拿到了上一個(gè)舊值。

          如何解決

          1. 重試機(jī)制

          我們可以采用消息隊(duì)列的思想去改進(jìn)。如果一條命令執(zhí)行成功,另一條命令執(zhí)行失敗時(shí),寫入消息隊(duì)列,進(jìn)入二次消費(fèi)。當(dāng)消費(fèi)成功時(shí),我們再把消息隊(duì)列的數(shù)據(jù)自行刪除。以免重復(fù)操作!

          這樣就保證了數(shù)據(jù)庫和緩存的一致性了!

          這種情況的確可以解決數(shù)據(jù)的一致性,但是如果這個(gè)數(shù)據(jù)被并發(fā)訪問的話,失敗的那一刻就造成了舊值的產(chǎn)生!我們再來分析一下

          • 先刪緩存,后更新數(shù)據(jù)庫

          假設(shè)緩存刪除成功之后,還沒進(jìn)行數(shù)據(jù)庫的更新操作,這時(shí)有個(gè)用戶請(qǐng)求打了過來。它發(fā)現(xiàn)緩存中不存在這個(gè)數(shù)據(jù),就會(huì)打到數(shù)據(jù)庫。它從數(shù)據(jù)庫中取到了數(shù)據(jù)。這就造成了讀到了舊值。而且讀到舊值的同時(shí)還會(huì)把舊值緩存到Redis中。

          隨后數(shù)據(jù)庫的更新操作開始進(jìn)行了。。。。

          緩存的值出現(xiàn)了,數(shù)據(jù)庫的值又沒了。。。。

          這兩者不就不一樣了嘛!

          我們在解決時(shí),一般都會(huì)讓他先sleep一小段時(shí)間,再進(jìn)行緩存刪除操作。sleep的睡眠參數(shù)取決于(線程讀數(shù)據(jù)和寫緩存的操作時(shí)間作為估值)

          • 先更新數(shù)據(jù)庫,后刪緩存

          如果數(shù)據(jù)庫的值修改了,刪除緩存的那一刻并發(fā)來了,用戶就會(huì)從緩存匯中讀取舊值直接返回給用戶。

          一擊要害!。。。。。

          刪除緩存值或更新數(shù)據(jù)庫失敗而導(dǎo)致數(shù)據(jù)不一致,你可以使用重試機(jī)制確保刪除或更新操作成功。

          在刪除緩存值、更新數(shù)據(jù)庫的這兩步操作中,有其他線程的并發(fā)讀操作,導(dǎo)致其他線程讀取到舊值,應(yīng)對(duì)方案是延遲雙刪。

          緩存雪崩,擊穿,穿透

          雪崩

          雪崩這個(gè)東西,見名思意。我們可以理解成一大堆雪沖了過來,一面墻無法抵擋猛烈的攻擊。于是沖垮了墻,直接沖向了你們家的臥室!

          一般造成緩存雪崩主要是有如下幾個(gè)原因

          • 發(fā)大洪水:系統(tǒng)設(shè)計(jì)問題,明明有100萬流量,程序只設(shè)計(jì)了10萬
          • 洪水從天而降的意外:緩存key剛好大面積失效,過期時(shí)間設(shè)計(jì)的不合理
          • 被瓦匠工糊弄了一下墻倒了:Redis實(shí)例宕機(jī)

          我們在平時(shí)解決時(shí),可以避免緩存寫入的時(shí)間大面積相同,可以在后面加一個(gè)隨機(jī)函數(shù),讓過期時(shí)間分布的頻段多一些。還可以通過服務(wù)降級(jí)來解決緩存雪崩。

          比如在去年新冠疫情的那會(huì)。嚴(yán)查所有過往的路人,一旦有咳嗽,發(fā)燒一律不予通行。如果沒有咳嗽,發(fā)燒等情況還持有體檢報(bào)告的可以回家自行隔離。

          在Redis中也是同樣道理,如果訪問的是核心數(shù)據(jù),我們可以放行,如果是訪問附加屬性我們可以直接返回初始數(shù)據(jù),或者網(wǎng)絡(luò)波動(dòng)問題。這樣就可以過濾一部分附加屬性的請(qǐng)求了。

          還有一種情況就是,洪水還沒來,墻自己倒了。你看這不是赤裸裸的求干嗎,你這不就是挑釁洪水的嘛。

          一般為了系統(tǒng)業(yè)務(wù)能正常運(yùn)行,我們會(huì)提前最好做好如下應(yīng)對(duì)措施

          1. 實(shí)現(xiàn)服務(wù)熔斷
          2. 實(shí)現(xiàn)請(qǐng)求限流機(jī)制。
          3. 高可用集群

          服務(wù)熔斷的話我們可以理解成,為了防止引發(fā)連鎖反應(yīng)(積分服務(wù)掛了,還能影響訂單嘛)我們關(guān)掉了用戶的積分服務(wù)。等修復(fù)成功之后再重新開啟服務(wù)。這樣就可以避免其他服務(wù)受此牽連。

          在業(yè)務(wù)系統(tǒng)運(yùn)行時(shí),我們可以監(jiān)測 Redis 緩存所在機(jī)器和數(shù)據(jù)庫所在機(jī)器的負(fù)載指標(biāo),例如每秒請(qǐng)求數(shù)、CPU 利用率、內(nèi)存利用率等。如果我們發(fā)現(xiàn) Redis 緩存實(shí)例宕機(jī)了,而數(shù)據(jù)庫所在機(jī)器的負(fù)載壓力突然增加(例如每秒請(qǐng)求數(shù)激增),此時(shí),就發(fā)生緩存雪崩了。大量請(qǐng)求被發(fā)送到數(shù)據(jù)庫進(jìn)行處理。我們可以啟動(dòng)服務(wù)熔斷機(jī)制,暫停業(yè)務(wù)應(yīng)用對(duì)緩存服務(wù)的訪問,從而降低對(duì)數(shù)據(jù)庫的訪問壓力

          服務(wù)限流的話,我們可以理解成早晨上班的警察道路調(diào)配。一個(gè)路口是流入量是不變的,如果我們想正常運(yùn)行,就必須把流入速率慢下來。

          回到系統(tǒng)的話就是每秒1萬個(gè)請(qǐng)求,限流之后,每秒1千個(gè)請(qǐng)求。再多的請(qǐng)求我們拒之門外排隊(duì)等候。

          高可用集群?的話也算是提前預(yù)防了。就好比在雙十一或者流量超級(jí)春運(yùn)的時(shí)候。流量超級(jí)大。我們提前在節(jié)日之前把對(duì)應(yīng)的機(jī)器設(shè)施架設(shè)起來。一旦大屏面板監(jiān)測到大批流量引入我們可以開啟備選方案,通過增加機(jī)器來解決并發(fā)需求。這樣也可以達(dá)到節(jié)省硬件成本的需求。

          擊穿

          緩存擊穿主要就是?熱點(diǎn)數(shù)據(jù)失效?。雙十一期間如果榜一的商品緩存失效了,恐怕就有悲劇了。一時(shí)間所有的請(qǐng)求都打到的數(shù)據(jù)庫上。這是由于熱點(diǎn)數(shù)據(jù)的過期時(shí)間設(shè)計(jì)不符導(dǎo)致的。

          我們一般對(duì)這類數(shù)據(jù)會(huì)進(jìn)行提前預(yù)熱,比如熱榜前100的數(shù)據(jù),我們會(huì)預(yù)熱30分鐘。這樣在秒殺的時(shí)候,就不會(huì)造成在短時(shí)間內(nèi)大量請(qǐng)求打入數(shù)據(jù)庫了。

          穿透

          緩存穿透顧名思義,就是在玩刺劍時(shí),攢足力氣,直沖一處。

          回到系統(tǒng)中是這樣的意思。黑客?在黑入我們系統(tǒng)時(shí),往往會(huì)猜想一些緩存中沒有的數(shù)據(jù),使大量請(qǐng)求打到數(shù)據(jù)庫,造成緩存穿透。當(dāng)下次再次請(qǐng)求時(shí),緩存中還是沒有查詢到,因?yàn)閺臄?shù)據(jù)庫查詢時(shí),本來就沒有所以也無法寫入緩存。

          我們的解決方案就是:不管數(shù)據(jù)庫是否存在當(dāng)前數(shù)據(jù),我們都緩存的一個(gè)key,給這個(gè)key的value中 寫入一個(gè)null。

          還可以利用Redis的布隆過濾器來解決。下面我們來聊一下什么是布隆過濾器

          布隆過濾器

          布隆過濾器由一個(gè)初值都為 0 的 bit 數(shù)組和 N 個(gè)哈希函數(shù)組成,可以用來快速判斷某個(gè)數(shù)據(jù)是否存在。當(dāng)我們想標(biāo)記某個(gè)數(shù)據(jù)存在時(shí)(例如,數(shù)據(jù)已被寫入數(shù)據(jù)庫),布隆過濾器會(huì)通過三個(gè)操作完成標(biāo)記:

          • 首先,使用 N 個(gè)哈希函數(shù),分別計(jì)算這個(gè)數(shù)據(jù)的哈希值,得到 N 個(gè)哈希值。
          • 然后,我們把這 N 個(gè)哈希值對(duì) bit 數(shù)組的長度取模,得到每個(gè)哈希值在數(shù)組中的對(duì)應(yīng)位置。
          • 最后,我們把對(duì)應(yīng)位置的 bit 位設(shè)置為 1,這就完成了在布隆過濾器中標(biāo)記數(shù)據(jù)的操作。

          如果數(shù)據(jù)不存在(例如,數(shù)據(jù)庫里沒有寫入數(shù)據(jù)),我們也就沒有用布隆過濾器標(biāo)記過數(shù)據(jù),那么,bit 數(shù)組對(duì)應(yīng) bit 位的值仍然為 0。

          當(dāng)需要查詢某個(gè)數(shù)據(jù)時(shí),我們就執(zhí)行剛剛說的計(jì)算過程,先得到這個(gè)數(shù)據(jù)在 bit 數(shù)組中對(duì)應(yīng)的 N 個(gè)位置。緊接著,我們查看 bit 數(shù)組中這 N 個(gè)位置上的 bit 值。只要這 N 個(gè) bit 值有一個(gè)不為 1,這就表明布隆過濾器沒有對(duì)該數(shù)據(jù)做過標(biāo)記,所以,查詢的數(shù)據(jù)一定沒有在數(shù)據(jù)庫中保存。

          緩存污染

          什么是緩存污染呢?

          在一些場景下,有些數(shù)據(jù)被訪問的次數(shù)非常少,甚至只會(huì)被訪問一次。當(dāng)這些數(shù)據(jù)服務(wù)完訪問請(qǐng)求后,如果還繼續(xù)留存在緩存中的話,就只會(huì)白白占用緩存空間。這種情況,就是緩存污染。

          如何解決?

          原本的計(jì)劃我是想把8種淘汰策略全部聊一遍的,但是看了下時(shí)間3點(diǎn)了。芭比Q了WC。

          速戰(zhàn)速?zèng)Q吧,通過前面的幾篇文章我們介紹了詳細(xì)的8種策略。這里的話我就直接省略了。

          • noeviction策略不進(jìn)行數(shù)據(jù)淘汰所以不能用于緩存污染
          • volatile-random與allkeys-random都是隨機(jī)淘汰,雖然可以用于淘汰數(shù)據(jù)但是不好,而且如果淘汰了熱點(diǎn)數(shù)據(jù)反而適得其反。
          • volatile-ttl屬于按照時(shí)間淘汰,和隨機(jī)淘汰一樣,用于解決緩存污染,不是很好,也會(huì)造成適得其反。

          剩下的四個(gè)volatile-lru、volatile-lfu、allkeys-lru、allkeys-lfu策略。其實(shí)我們可以看成2個(gè)策略,只不過一個(gè)是局部的一個(gè)是全局的。為了理解我們下面就用?LRU?和?LFU?算法表示。

          LRU

          廢話不多說,省略一些,想看詳細(xì)的可以去(3萬聊聊什么是Redis五)。LRU算法是比較好的,但是唯一的缺點(diǎn)就是?受訪問時(shí)間影響,因?yàn)橹豢磾?shù)據(jù)的訪問時(shí)間,使用 LRU 策略在處理掃描式單次查詢操作時(shí),無法解決緩存污染。所謂的掃描式單次查詢操作,就是指應(yīng)用對(duì)大量的數(shù)據(jù)進(jìn)行一次全體讀取,每個(gè)數(shù)據(jù)都會(huì)被讀取,而且只會(huì)被讀取一次。此時(shí),因?yàn)檫@些被查詢的數(shù)據(jù)剛剛被訪問過,所以 lru 字段值都很大。

          LRU會(huì)把這些數(shù)據(jù)在留在緩存中很長時(shí),造成緩存污染。如果有新數(shù)據(jù)訪問時(shí),還要把舊數(shù)據(jù)替換出去,換新的值進(jìn)來,這樣會(huì)影響緩存的性能。

          LFU

          在LRU的基礎(chǔ)上,誕生了LFU算法。

          LFU 緩存策略是在 LRU 策略基礎(chǔ)上,為每個(gè)數(shù)據(jù)增加了一個(gè)計(jì)數(shù)器,來統(tǒng)計(jì)這個(gè)數(shù)據(jù)的訪問次數(shù)。當(dāng)使用 LFU 策略篩選淘汰數(shù)據(jù)時(shí),首先會(huì)根據(jù)數(shù)據(jù)的訪問次數(shù)進(jìn)行篩選,把訪問次數(shù)最低的數(shù)據(jù)淘汰出緩存。如果兩個(gè)數(shù)據(jù)的訪問次數(shù)相同,LFU 策略再比較這兩個(gè)數(shù)據(jù)的訪問時(shí)效性,把距離上一次訪問時(shí)間更久的數(shù)據(jù)淘汰出緩存。

          和那些被頻繁訪問的數(shù)據(jù)相比,掃描式單次查詢的數(shù)據(jù)因?yàn)椴粫?huì)被再次訪問,所以它們的訪問次數(shù)不會(huì)再增加。因此,LFU 策略會(huì)優(yōu)先把這些訪問次數(shù)低的數(shù)據(jù)淘汰出緩存。這樣一來,LFU 策略就可以避免這些數(shù)據(jù)對(duì)緩存造成污染了。

          LFU為了造成鏈表的開銷,使用了兩個(gè)近似的方案

          1. 都可以RedisObject 保存數(shù)據(jù),在結(jié)構(gòu)內(nèi)設(shè)置了一個(gè)lru字段記錄數(shù)據(jù)的時(shí)間戳
          2. 采用隨機(jī)采樣的方式選取一定數(shù)據(jù)量放入候選集合,后續(xù)在候選集合中根據(jù)lru字段值的大小進(jìn)行篩選。

          Redis 在實(shí)現(xiàn) LFU 策略的時(shí)候,只是把原來 24bit 大小的 lru 字段,又進(jìn)一步拆分成了兩部分。

          • ldt 值:lru 字段的前 16bit,表示數(shù)據(jù)的訪問時(shí)間戳;
          • counter 值:lru 字段的后 8bit,表示數(shù)據(jù)的訪問次數(shù)。

          LFU這里用到了一個(gè)很有意思的設(shè)計(jì)。它采用的是8字段存儲(chǔ)訪問次數(shù)。我們得知8字節(jié)可以存放255次,如果超過255Redis如何響應(yīng)呢?

          Redis寫滿之后,會(huì)使用LFU策略進(jìn)行數(shù)據(jù)淘汰。當(dāng)兩個(gè)值都是255時(shí),再去比較時(shí)間戳。但是以Redis的訪問請(qǐng)求量遠(yuǎn)遠(yuǎn)不夠。因此,在實(shí)現(xiàn) LFU 策略時(shí),Redis 并沒有采用數(shù)據(jù)每被訪問一次,就給對(duì)應(yīng)的 counter 值加 1 的計(jì)數(shù)規(guī)則,而是采用了一個(gè)更優(yōu)化的計(jì)數(shù)規(guī)則。

          每當(dāng)數(shù)據(jù)被訪問一次時(shí),首先,用計(jì)數(shù)器當(dāng)前的值乘以配置項(xiàng) lfu_log_factor 再加 1,再取其倒數(shù),得到一個(gè) p 值;然后,把這個(gè) p 值和一個(gè)取值范圍在(0,1)間的隨機(jī)數(shù) r 值比大小,只有 p 值大于 r 值時(shí),計(jì)數(shù)器才加 1。

          當(dāng)?lfu_log_factor?為1時(shí),實(shí)際訪問次數(shù)為 100K 后,counter 值就達(dá)到 255 了,無法再區(qū)分實(shí)際訪問次數(shù)更多的數(shù)據(jù)了。

          當(dāng) lfu_log_factor 取值為 10 時(shí),百、千、十萬級(jí)別的訪問次數(shù)對(duì)應(yīng)的 counter 值已經(jīng)有明顯的區(qū)分了(一般應(yīng)用時(shí),我們可以設(shè)置為10)

          當(dāng)?lfu_log_factor?為100時(shí),當(dāng)實(shí)際訪問次數(shù)為 10M 時(shí),counter 值才達(dá)到 255,此時(shí),實(shí)際訪問次數(shù)小于 10M 的不同數(shù)據(jù)都可以通過 counter 值區(qū)分出來。

          結(jié)尾

          大概總結(jié)了

          1. 緩存和數(shù)據(jù)不一致性引發(fā)的問題
          2. 不同的緩存類型以及解決訪問。
          3. Redis常見的生產(chǎn)問題,緩存雪崩,擊穿,穿透,
          4. 由穿透又聊到了布隆過濾器
          5. 緩存污染以及應(yīng)用措施,順帶的聊了一下LFU和LRU的經(jīng)典之處

          學(xué)完之后,我只能驚嘆一下Redis作者太牛了,這種設(shè)計(jì)的思路也值得我們?nèi)蘸蟮南到y(tǒng)中借鑒一下。

          這篇文章應(yīng)該沒有前幾篇好一些,這周我們公司的總監(jiān)臨時(shí)有事,然后我自己扛起了一面小旗,所有的學(xué)習(xí)時(shí)間都是每天晚上零散一些。周六白天又在給電商那套系統(tǒng)開發(fā)新的功能。晚上回憶了一下本周的知識(shí)碎片,敖到凌晨3點(diǎn)才完工的一篇。

          每個(gè)知識(shí)點(diǎn)都是自己整理濃縮表達(dá)出來的,部分有些不容易懂的地方請(qǐng)及時(shí)指出,我們一起共同進(jìn)步!

          因?yàn)榇_實(shí)比較累的緣故,部分知識(shí)出自蔣德均老師,Redis設(shè)計(jì)與實(shí)現(xiàn),Redis深度歷險(xiǎn)。尊重原創(chuàng)!

          非常歡迎大家加我個(gè)人微信有關(guān)后端方面的問題我們在群內(nèi)一起討論!?我們下期再見!

          長按上方掃碼二維碼,加我微信,拉你進(jìn)群


          瀏覽 38
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲内射电影 | 日韩伦理精品在线 | 亚洲成人视频在线免费观看 | 日本黄色视频免费 | 青娱乐在线观看网址 |