<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>

          多圖深入理解 Redis

          共 12027字,需瀏覽 25分鐘

           ·

          2022-11-04 03:45

          在公眾號后臺回復(fù): JGNB ,可獲取杰哥原創(chuàng)的 PDF 手冊。

          大家好,我是杰哥。

          Redis 現(xiàn)在應(yīng)該是各大廠標(biāo)配了,不過可能很多人只懂得怎么用,但對其原理不甚了解,今天我們就用圖解的形式來深入了解 Redis 高性能,高可用的秘密

          什么是 Redis?

          Redis(REmote DIctionary Service)是一個開源的鍵值對數(shù)據(jù)庫服務(wù)器。

          Redis 更準(zhǔn)確的描述是一個數(shù)據(jù)結(jié)構(gòu)服務(wù)器。Redis 的這種特殊性質(zhì)讓它在開發(fā)人員中很受歡迎。

          d751a37c6e6a81fe41d1b076adca660e.webp

          Redis不是通過迭代或者排序方式處理數(shù)據(jù),而是一開始就按照數(shù)據(jù)結(jié)構(gòu)方式組織。早期,它的使用很像 Memcached,但隨著 Redis 的改進(jìn),它在許多其他用例中變得可行,包括發(fā)布-訂閱機(jī)制、流(streaming)和隊列。

          dd4f7756f8f4100a53c0b9abce1b384f.webp

          主要來說,Redis 是一個內(nèi)存數(shù)據(jù)庫,用作另一個“真實(shí)”數(shù)據(jù)庫(如 MySQL 或 PostgreSQL)前面的緩存,以幫助提高應(yīng)用程序性能。它通過利用內(nèi)存的高速訪問速度,從而減輕核心應(yīng)用程序數(shù)據(jù)庫的負(fù)載,例如:

          • 不經(jīng)常更改且經(jīng)常被請求的數(shù)據(jù)

          • 任務(wù)關(guān)鍵性較低且經(jīng)常變動的數(shù)據(jù)

          上述數(shù)據(jù)的示例可以包括會話或數(shù)據(jù)緩存以及儀表板的排行榜或匯總分析。

          7c4973cef3f41e6082500b67dca93d4a.webp

          但是,對于許多用例場景,Redis 都可以提供足夠的保證,可以將其用作成熟的主數(shù)據(jù)庫。再加上 Redis 插件及其各種高可用性(HA)設(shè)置,Redis 作為數(shù)據(jù)庫對于某些場景和工作負(fù)載變得非常有用。

          另一個重要方面是 Redis 模糊了緩存和數(shù)據(jù)存儲之間的界限。這里要理解的重要一點(diǎn)是,相比于使用 SSD 或 HDD 作為存儲的傳統(tǒng)數(shù)據(jù)庫,讀取和操作內(nèi)存中數(shù)據(jù)的速度要快得多。

          08f49c2ee25051a08197aa5fb1bc1682.webp

          最初,Redis 最常被比作 Memcached,后者當(dāng)時缺乏任何非易失性持久化。

          這是當(dāng)前兩個緩存之間的功能細(xì)分。

          45fc7b7139c4f911c533ec286fe781b2.webp

          雖然現(xiàn)在擁有多種配置方式將數(shù)據(jù)持久化到磁盤,但當(dāng)時首次引入持久化時,Redis 是使用快照方式,通過異步拷貝內(nèi)存中的數(shù)據(jù)方式來做持久化。不幸的是,這種機(jī)制的缺點(diǎn)是可能會在快照之間丟失數(shù)據(jù)。

          Redis 自 2009 年成立到現(xiàn)在已經(jīng)變的很成熟。我們將介紹它的大部分架構(gòu)和拓?fù)洌员隳憧梢詫?Redis 添加到你的數(shù)據(jù)存儲系統(tǒng)庫中。

          Redis 架構(gòu)

          在開始討論 Redis 內(nèi)部結(jié)構(gòu)之前,讓我們先討論一下各種 Redis 部署及其權(quán)衡取舍。

          我們將主要關(guān)注以下這些設(shè)置:

          • 單個 Redis 實(shí)例

          • Redis 高可用性

          • Redis 哨兵

          • Redis 集群

          根據(jù)你的用例和規(guī)模,決定使用哪一種設(shè)置。

          單個 Redis 實(shí)例

          1f3dec8bd2e9ded59bfec4230f34f320.webp

          單個 Redis 實(shí)例是最直接的 Redis 部署方式。它允許用戶設(shè)置和運(yùn)行小型實(shí)例,從而幫助他們快速發(fā)展和加速服務(wù)。但是,這種部署并非沒有缺點(diǎn)。例如,如果此實(shí)例失敗或不可用,則所有客戶端對 Redis 的調(diào)用都將失敗,從而降低系統(tǒng)的整體性能和速度。

          如果有足夠的內(nèi)存和服務(wù)器資源,這個實(shí)例可以很強(qiáng)大。主要用于緩存的場景可能會以最少的設(shè)置獲得顯著的性能提升。給定足夠的系統(tǒng)資源,你可以在應(yīng)用程序運(yùn)行的同一機(jī)器上部署此 Redis 服務(wù)。

          在管理系統(tǒng)內(nèi)的數(shù)據(jù)方面,了解一些 Redis 概念是必不可少的。發(fā)送到 Redis 的命令首先在內(nèi)存中處理。然后,如果在這些實(shí)例上設(shè)置了持久性,則在某個時間間隔上會有一個fork進(jìn)程,來生成數(shù)據(jù)持久化 RDB(Redis 數(shù)據(jù)的非常緊湊的時間點(diǎn)表示)快照或 AOF(僅附加文件)。

          這兩個流程可以讓 Redis 擁有長期存儲,支持各種復(fù)制策略,并啟用更復(fù)雜的拓?fù)洹H绻?Redis 未設(shè)置為持久化數(shù)據(jù),則在重新啟動或故障轉(zhuǎn)移時數(shù)據(jù)會丟失。如果在重啟時啟用了持久化,它會將 RDB 快照或 AOF 中的所有數(shù)據(jù)加載回內(nèi)存,然后實(shí)例可以支持新的客戶端請求。

          話雖如此,讓我們看看你可能會用到的更多分布式 Redis 設(shè)置。

          Redis 高可用性

          08de3e3063b4f89ca16d36e2dfd5ec83.webp

          Redis 的另一個流行設(shè)置是主從部署方式,從部署保持與主部署之間數(shù)據(jù)同步。當(dāng)數(shù)據(jù)寫入主實(shí)例時,它會將這些命令的副本發(fā)送到從部署客戶端輸出緩沖區(qū),從而達(dá)到數(shù)據(jù)同步的效果。從部署可以有一個或多個實(shí)例。這些實(shí)例可以幫助擴(kuò)展 Redis 的讀取操作或提供故障轉(zhuǎn)移,以防 main 丟失。

          我們現(xiàn)在已經(jīng)進(jìn)入了一個分布式系統(tǒng),因此需要在此拓?fù)渲锌紤]許多新事物。以前簡單的事情現(xiàn)在變得復(fù)雜了。

          Redis 復(fù)制

          Redis 的每個主實(shí)例都有一個復(fù)制 ID 和一個偏移量。這兩條數(shù)據(jù)對于確定副本可以繼續(xù)其復(fù)制過程的時間點(diǎn)或確定它是否需要進(jìn)行完整同步至關(guān)重要。對于主 Redis 部署上發(fā)生的每個操作,此偏移量都會增加。

          更明確地說,當(dāng) Redis 副本實(shí)例僅落后于主實(shí)例幾個偏移量時,它會從主實(shí)例接收剩余的命令,然后在其數(shù)據(jù)集上重放,直到同步完成。如果兩個實(shí)例無法就復(fù)制 ID 達(dá)成一致,或者主實(shí)例不知道偏移量,則副本將請求全量同步。這時主實(shí)例會創(chuàng)建一個新的 RDB 快照并將其發(fā)送到副本。

          在此傳輸之間,主實(shí)例會緩沖快照截止和當(dāng)前偏移之間的所有中間更新指令,這樣在快照同步完后,再將這些指令發(fā)送到副本實(shí)例。這樣完成后,復(fù)制就可以正常繼續(xù)。

          如果一個實(shí)例具有相同的復(fù)制 ID 和偏移量,則它們具有完全相同的數(shù)據(jù)。現(xiàn)在你可能想知道為什么需要復(fù)制 ID。當(dāng) Redis 實(shí)例被提升為主實(shí)例或作為主實(shí)例從頭開始重新啟動時,它會被賦予一個新的復(fù)制 ID。

          這用于推斷此新提升的副本實(shí)例是從先前哪個主實(shí)例復(fù)制出來的。這允許它能夠執(zhí)行部分同步(與其他副本節(jié)點(diǎn)),因?yàn)樾碌闹鲗?shí)例會記住其舊的復(fù)制 ID。

          例如,兩個實(shí)例(主實(shí)例和從實(shí)例)具有相同的復(fù)制 ID,但偏移量相差幾百個命令,這意味著如果在實(shí)例上重放這些偏移量后面的命令,它們將具有相同的數(shù)據(jù)集。現(xiàn)在,如果復(fù)制 ID 完全不同,并且我們不知道新降級(或重新加入)從節(jié)點(diǎn)的先前復(fù)制 ID(沒有共同祖先)。我們將需要執(zhí)行昂貴的全量同步。

          相反,如果我們知道以前的復(fù)制 ID,我們就可以推斷如何使數(shù)據(jù)同步,因?yàn)槲覀兡軌蛲茢喑鏊鼈児蚕淼墓餐嫦龋⑶移屏繉τ诓糠滞皆俅斡幸饬x。

          Redis 哨兵(Sentinel)

          3bb85dc354526d3b4e3327986117ad44.webp

          Sentinel 是一個分布式系統(tǒng)。與所有分布式系統(tǒng)一樣,Sentinel 有幾個優(yōu)點(diǎn)和缺點(diǎn)。Sentinel 的設(shè)計方式是,一組哨兵進(jìn)程協(xié)同工作以協(xié)調(diào)狀態(tài),從而為 Redis 提供高可用性。畢竟,你不希望保護(hù)你免受故障影響的系統(tǒng)有自己的單點(diǎn)故障。

          Sentinel 負(fù)責(zé)一些事情。首先,它確保當(dāng)前的主實(shí)例和從實(shí)例正常運(yùn)行并做出響應(yīng)。這是必要的,因?yàn)樯诒ㄅc其他哨兵進(jìn)程)可以在主節(jié)點(diǎn)和/或從節(jié)點(diǎn)丟失的情況下發(fā)出警報并采取行動。其次,它在服務(wù)發(fā)現(xiàn)中發(fā)揮作用,就像其他系統(tǒng)中的 Zookeeper 和 Consul 一樣。所以當(dāng)一個新的客戶端嘗試向 Redis 寫東西時,Sentinel 會告訴客戶端當(dāng)前的主實(shí)例是什么。

          因此,哨兵不斷監(jiān)控可用性并將該信息發(fā)送給客戶端,以便他們能夠在他們確實(shí)進(jìn)行故障轉(zhuǎn)移時對其做出反應(yīng)。

          以下是它的職責(zé):

          • 監(jiān)控——確保主從實(shí)例按預(yù)期工作。

          • 通知——通知系統(tǒng)管理員 Redis 實(shí)例中的事件。

          • 故障轉(zhuǎn)移管理——如果主實(shí)例不可用并且足夠多的(法定數(shù)量)節(jié)點(diǎn)同意這是真的,Sentinel 節(jié)點(diǎn)可以啟動故障轉(zhuǎn)移。

          • 配置管理——Sentinel 節(jié)點(diǎn)還充當(dāng)當(dāng)前主 Redis 實(shí)例的發(fā)現(xiàn)服務(wù)。

          以這種方式使用 Redis Sentinel 可以進(jìn)行故障檢測。此檢測涉及多個哨兵進(jìn)程同意當(dāng)前主實(shí)例不再可用。這個協(xié)議過程稱為 Quorum。這可以提高魯棒性并防止一臺機(jī)器行為異常導(dǎo)致無法訪問主 Redis 節(jié)點(diǎn)。

          此設(shè)置并非沒有缺點(diǎn),因此我們將在使用 Redis Sentinel 時介紹一些建議和最佳實(shí)踐。

          你可以通過多種方式部署 Redis Sentinel。老實(shí)說,要提出任何明智的建議,我需要有關(guān)你的系統(tǒng)的更多背景信息。作為一般指導(dǎo),我建議在每個應(yīng)用程序服務(wù)器旁邊運(yùn)行一個哨兵節(jié)點(diǎn)(如果可能的話),這樣你也不需要考慮哨兵節(jié)點(diǎn)和實(shí)際使用 Redis 的客戶端之間的網(wǎng)絡(luò)可達(dá)性差異。

          你可以將 Sentinel 與 Redis 實(shí)例一起運(yùn)行,甚至可以在獨(dú)立節(jié)點(diǎn)上運(yùn)行,只不過它會按照別的方式處理,從而會讓事情變得更復(fù)雜。我建議至少運(yùn)行三個節(jié)點(diǎn),并且至少具有兩個法定人數(shù)(quorum)。這是一個簡單的圖表,分解了集群中的服務(wù)器數(shù)量以及相關(guān)的法定人數(shù)和可容忍的可持續(xù)故障。

          a6a44db527c01c0aba684603ca9abb05.webp

          這會因系統(tǒng)而異,但總體思路是不變的。

          讓我們花點(diǎn)時間思考一下這樣的設(shè)置會出現(xiàn)什么問題。如果你運(yùn)行這個系統(tǒng)足夠長的時間,你會遇到所有這些。

          1、如果哨兵節(jié)點(diǎn)超出法定人數(shù)怎么辦?

          2、如果網(wǎng)絡(luò)分裂將舊的主實(shí)例置于少數(shù)群體中怎么辦?這些寫入會發(fā)生什么?(劇透:當(dāng)系統(tǒng)完全恢復(fù)時它們會丟失)

          3、如果哨兵節(jié)點(diǎn)和客戶端節(jié)點(diǎn)(應(yīng)用程序節(jié)點(diǎn))的網(wǎng)絡(luò)拓?fù)溴e位會發(fā)生什么?

          沒有持久性保證,特別是持久化到磁盤的操作(見下文)是異步的。還有一個麻煩的問題,當(dāng)客戶發(fā)現(xiàn)新的 primary 時,我們失去了多少寫給一個不知道的 primary?Redis 建議在建立新連接時查詢新的主節(jié)點(diǎn)。根據(jù)系統(tǒng)配置,這可能意味著大量數(shù)據(jù)丟失。

          如果你強(qiáng)制主實(shí)例將寫入復(fù)制到至少一個副本實(shí)例,有幾種方法可以減輕損失程度。請記住,所有 Redis 復(fù)制都是異步的,這是有其權(quán)衡的考慮。因此,它需要獨(dú)立跟蹤確認(rèn),如果至少有一個副本實(shí)例沒有確認(rèn)它們,主實(shí)例將停止接受寫入。

          Redis 集群

          c6c440dd7ca86d5df3f5105fe0cf7b05.webp

          我相信很多人都想過當(dāng)你無法將所有數(shù)據(jù)存儲在一臺機(jī)器上的內(nèi)存中時會發(fā)生什么。目前,單個服務(wù)器中可用的最大 RAM 為 24TIB,這是目前 AWS 線上列出來的。當(dāng)然,這很多,但對于某些系統(tǒng)來說,這還不夠,即使對于緩存層也是如此。

          Redis Cluster 允許 Redis 的水平擴(kuò)展。

          首先,讓我們擺脫一些術(shù)語約束;一旦我們決定使用 Redis 集群,我們就決定將我們存儲的數(shù)據(jù)分散到多臺機(jī)器上,這稱為分片。所以集群中的每個 Redis 實(shí)例都被認(rèn)為是整個數(shù)據(jù)的一個分片。

          這帶來了一個新的問題。如果我們向集群推送一個key,我們?nèi)绾沃滥膫€ Redis 實(shí)例(分片)保存了該數(shù)據(jù)?有幾種方法可以做到這一點(diǎn),但 Redis Cluster 使用算法分片。

          為了找到給定 key 的分片,我們對 key 進(jìn)行哈希處理,并通過對總分片數(shù)量取模。然后,使用確定性哈希函數(shù),這意味著給定的 key 將始終映射到同一個分片,我們可以推斷將來讀取特定 key 的位置。

          當(dāng)我們之后想在系統(tǒng)中添加一個新的分片時會發(fā)生什么?這個過程稱為重新分片。

          假設(shè)鍵 'foo' 之前映射到分片 0, 在引入新分片后它可能會映射到分片 5。但是,如果我們需要快速擴(kuò)展系統(tǒng),移動數(shù)據(jù)來達(dá)到新的分片映射,這將是緩慢且不切實(shí)際的。它還對 Redis 集群的可用性產(chǎn)生不利影響。

          Redis Cluster 為這個問題設(shè)計了一種解決方案,稱為 Hashslot,所有數(shù)據(jù)都映射到它。有 16K 哈希槽。這為我們提供了一種在集群中傳播數(shù)據(jù)的合理方式,當(dāng)我們添加新的分片時,我們只需在系統(tǒng)之間移動哈希槽。通過這樣做,我們只需要將 hashlot 從一個分片移動到另一個分片,并簡化將新的主實(shí)例添加到集群中的過程。

          這可以在沒有任何停機(jī)時間和最小的性能影響的情況下實(shí)現(xiàn)。讓我們通過一個例子來談?wù)劇?/p>

          • M1 包含從 0 到 8191 的哈希槽。

          • M2 包含從 8192 到 16383 的哈希槽。

          因此,為了映射 “foo”,我們采用一個確定性的鍵(foo)散列,并通過散列槽的數(shù)量(16K)對其進(jìn)行修改,從而得到 M2 的映射。現(xiàn)在假設(shè)我們添加了一個新實(shí)例 M3。新的映射將是:

          • M1 包含從 0 到 5460 的哈希槽。

          • M2 包含從 5461 到 10922 的哈希槽。

          • M3 包含從 10923 到 16383 的哈希槽。

          現(xiàn)在映射到 M2 的 M1 中映射哈希槽的所有鍵都需要移動。但是散列槽的各個鍵的散列不需要移動,因?yàn)樗鼈円呀?jīng)被劃分到散列槽中。因此,這一級別的誤導(dǎo)(misdirection)解決了算法分片的重新分片問題。

          Gossiping 協(xié)議

          Redis Cluster 使用 gossiping 來確定整個集群的健康狀況。在上圖中,我們有 3 個 M 個節(jié)點(diǎn)和 3 個 S 節(jié)點(diǎn)。所有這些節(jié)點(diǎn)不斷地進(jìn)行通信以了解哪些分片可用并準(zhǔn)備好為請求提供服務(wù)。

          如果足夠多的分片同意 M1 沒有響應(yīng),他們可以決定將 M1 的副本 S1 提升為主節(jié)點(diǎn)以保持集群健康。觸發(fā)此操作所需的節(jié)點(diǎn)數(shù)量是可配置的,并且必須正確執(zhí)行此操作。如果操作不當(dāng)并且在分區(qū)的兩邊相等時無法打破平局,則可能會導(dǎo)致集群被拆分。這種現(xiàn)象稱為裂腦。作為一般規(guī)則,必須擁有奇數(shù)個主節(jié)點(diǎn)和兩個副本,以實(shí)現(xiàn)最穩(wěn)健的設(shè)置。

          Redis 持久化模型

          如果我們要使用 Redis 存儲任何類型的數(shù)據(jù)同時要求安全保存,了解 Redis 是如何做到這一點(diǎn)很重要。在許多用例中,如果你丟失了 Redis 存儲的數(shù)據(jù),這并不是世界末日。將其用作緩存或在其支持實(shí)時分析的情況下,如果發(fā)生數(shù)據(jù)丟失,則并非世界末日。

          在其他場景中,我們希望圍繞數(shù)據(jù)持久性和恢復(fù)有一些保證。

          3d682ad8e71cf4b1f0d180f9c14ee14c.webp

          無持久化

          無持久化:如果你愿意,可以完全禁用持久化。這是運(yùn)行 Redis 的最快方式,并且沒有持久性保證。

          RDB文件

          RDB(Redis 數(shù)據(jù)庫):RDB 持久化以指定的時間間隔執(zhí)行數(shù)據(jù)集的時間點(diǎn)快照。

          這種機(jī)制的主要缺點(diǎn)是快照之間的數(shù)據(jù)會丟失。此外,這種存儲機(jī)制還依賴于主進(jìn)程的 fork,在更大的數(shù)據(jù)集中,這可能會導(dǎo)致服務(wù)請求的瞬間延遲。話雖如此,RDB 文件在內(nèi)存中的加載速度要比 AOF 快得多。

          AOF

          AOF(Append Only File):AOF 持久化記錄服務(wù)器接收到的每個寫入操作,這些操作將在服務(wù)器啟動時再次被執(zhí)行,重建原始數(shù)據(jù)集。

          這種持久性的方法能夠確保比 RDB 快照更持久,因?yàn)樗且粋€僅附加文件。隨著操作的發(fā)生,我們將它們緩沖到日志中,但它們還沒有被持久化。該日志與我們運(yùn)行的實(shí)際命令一致,以便在需要時進(jìn)行重放。

          然后,如果可能,我們使用 fsync 將其刷新到磁盤(當(dāng)此運(yùn)行可配置時),它將被持久化。缺點(diǎn)是格式不緊湊,并且比 RDB 文件使用更多的磁盤。

          為什么不兼得?

          RDB + AOF:可以將 AOF 和 RDB 組合在同一個 Redis 實(shí)例中。如果你愿意的話,可以以速度換取持久化是一種折衷方法。我認(rèn)為這是設(shè)置 Redis 的一種可接受的方式。在重啟的情況下,請記住如果兩者都啟用,Redis 將使用 AOF 來重建數(shù)據(jù),因?yàn)樗亲钔暾摹?/p>

          Forking

          現(xiàn)在我們了解了持久化的類型,讓我們討論一下我們?nèi)绾卧谙?Redis 這樣的單線程應(yīng)用程序中實(shí)際執(zhí)行它。

          a8067a5dfb9222f70c7967eb41fe9702.webp

          在我看來,Redis 最酷的部分是它如何利用 forking 和寫時復(fù)制來高效地促進(jìn)數(shù)據(jù)持久化。

          Forking 是操作系統(tǒng)通過創(chuàng)建自身副本來創(chuàng)建新進(jìn)程的一種方式。這樣,你將獲得一個新的進(jìn)程 ID 和一些其他信息和句柄,因此新 forking 的進(jìn)程(子進(jìn)程)可以與原始進(jìn)程父進(jìn)程通信。

          現(xiàn)在事情變得有趣了。Redis 是一個分配了大量內(nèi)存的進(jìn)程,那么它如何在不耗盡內(nèi)存的情況下進(jìn)行復(fù)制呢?

          當(dāng)你 fork 一個進(jìn)程時,父進(jìn)程和子進(jìn)程共享內(nèi)存,并且在該子進(jìn)程中 Redis 開始快照(Redis)進(jìn)程。這是通過一種稱為寫時復(fù)制的內(nèi)存共享技術(shù)實(shí)現(xiàn)的——該技術(shù)在創(chuàng)建分叉時傳遞對內(nèi)存的引用。如果在子進(jìn)程持久化到磁盤時沒有發(fā)生任何更改,則不會進(jìn)行新的分配。

          在發(fā)生更改的情況下,內(nèi)核會跟蹤對每個頁面的引用,如果某個頁面有多個更改,則將更改寫入新頁面。子進(jìn)程完全不知道更改以及具有一致的內(nèi)存快照的事情。因此,在只使用了一小部分內(nèi)存的情況下,我們能夠非常快速有效地獲得潛在千兆字節(jié)內(nèi)存的時間點(diǎn)快照!

          推薦閱讀:

          Redis 知識總結(jié)


          一文讀懂 Redis!


          4 種 Redis 集群方案介紹 + 優(yōu)缺點(diǎn)對比


          50 個 Redis 必備知識:基礎(chǔ)知識,架構(gòu)、調(diào)優(yōu)和監(jiān)控知識及難點(diǎn)解決


          學(xué)會這幾個 Redis 技巧,讓你的程序快如閃電!


          Redis 主從握手流程


          一口氣說出 Redis 16 個常見使用場景


          Redis 主從復(fù)制、哨兵模式、集群


          萬字總結(jié),Redis 性能問題排查解決手冊!

          2fbd01deab84291bab7c7c9fdef91676.webp

          瀏覽 58
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <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>
                  一道本高清无码视频 | 精品传媒一区二区 | 亚洲日频看视频网站 | 欧美一级内射 | 综合在线一区 |