<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之?dāng)?shù)據(jù)類型、過期刪除、持久化

          共 6291字,需瀏覽 13分鐘

           ·

          2022-06-27 17:04

          這里對(duì)Redis的數(shù)據(jù)類型、過期刪除、持久化等方面進(jìn)行介紹

          abstract.png

          數(shù)據(jù)類型

          String 字符串

          Redis的object encoding命令可以返回Redis對(duì)象所使用的編碼。進(jìn)而可幫助我們了解Redis某種數(shù)據(jù)類型的內(nèi)部實(shí)現(xiàn)方式。具體地,對(duì)于String字符串類型的數(shù)據(jù)內(nèi)部的實(shí)現(xiàn)方式有以下幾種情況

          • 值為整數(shù),且可以用long類型來表示,則該值可以直接用long表示。相應(yīng)object encoding命令的編碼值為int
          • 值為字符串,且長(zhǎng)度大于指定長(zhǎng)度,則該值會(huì)使用簡(jiǎn)單動(dòng)態(tài)字符串SDS表示。相應(yīng)object encoding命令的編碼值為raw
          • 值為字符串,且長(zhǎng)度不大于指定長(zhǎng)度,則該值會(huì)使用embstr編碼的簡(jiǎn)單動(dòng)態(tài)字符串SDS進(jìn)行表示。相應(yīng)object encoding命令的編碼值為embstr

          測(cè)試結(jié)果,如下所示

          figure 1.jpeg

          List 列表

          在Redis 3.2之前對(duì)于List類型的數(shù)據(jù)而言,其內(nèi)部有兩種實(shí)現(xiàn)方式

          • 列表中元素?cái)?shù)量小于一定數(shù)量 且 各元素字符串的長(zhǎng)度均小于一定長(zhǎng)度,其內(nèi)部會(huì)使用linkedlist雙向鏈表進(jìn)行實(shí)現(xiàn)
          • 對(duì)于不滿足上述條件的情形,其內(nèi)部會(huì)使用ziplist壓縮鏈表進(jìn)行實(shí)現(xiàn)

          而從Redis 3.2開始,對(duì)于List類型的數(shù)據(jù)則統(tǒng)一通過quickList進(jìn)行實(shí)現(xiàn),測(cè)試結(jié)果,如下所示

          figure 2.jpeg

          Hash 哈希

          對(duì)于Hash哈希類型的數(shù)據(jù)內(nèi)部的實(shí)現(xiàn)方式有以下幾種情況

          • 哈希表中鍵值對(duì)小于一定數(shù)量 且 哈希表中所有鍵、值的字符串長(zhǎng)度均小于一定長(zhǎng)度,其內(nèi)部會(huì)使用ziplist壓縮鏈表進(jìn)行實(shí)現(xiàn)
          • 對(duì)于不滿足上述條件的情形,其內(nèi)部會(huì)使用dict字典進(jìn)行實(shí)現(xiàn)。相應(yīng)object encoding命令的編碼值為hashtable

          測(cè)試結(jié)果,如下所示

          figure 3.jpeg

          Set 集合

          對(duì)于Set集合類型的數(shù)據(jù)內(nèi)部的實(shí)現(xiàn)方式有以下幾種情況

          • 集合中元素小于一定數(shù)量 且 所有元素均為整數(shù),其內(nèi)部會(huì)使用intset整數(shù)集合進(jìn)行實(shí)現(xiàn)。其中intset整數(shù)集合本質(zhì)上是整型數(shù)組
          • 對(duì)于不滿足上述條件的情形,其內(nèi)部會(huì)使用dict字典進(jìn)行實(shí)現(xiàn)。相應(yīng)object encoding命令的編碼值為hashtable

          測(cè)試結(jié)果,如下所示

          figure 4.jpeg

          Zset 有序集合

          對(duì)于Zset集合類型的數(shù)據(jù)內(nèi)部的實(shí)現(xiàn)方式有以下幾種情況

          • 集合中元素小于一定數(shù)量 且 各元素字符串的長(zhǎng)度均小于一定長(zhǎng)度,其內(nèi)部會(huì)使用ziplist壓縮列表進(jìn)行實(shí)現(xiàn)
          • 對(duì)于不滿足上述條件的情形,其內(nèi)部會(huì)使用skiplist跳表進(jìn)行實(shí)現(xiàn)

          測(cè)試結(jié)果,如下所示

          figure 5.jpeg

          值得一提的是當(dāng)通過skiplist跳表實(shí)現(xiàn)Zset時(shí),其內(nèi)部還會(huì)同時(shí)使用dict字典。以便在根據(jù)元素查詢分?jǐn)?shù)時(shí),可以實(shí)現(xiàn)常數(shù)時(shí)間復(fù)雜度;而無需通過遍歷跳表來獲取

          內(nèi)部數(shù)據(jù)結(jié)構(gòu)

          SDS 簡(jiǎn)單動(dòng)態(tài)字符串

          在C中只能通過字符數(shù)組來表示字符串,此舉顯然無法滿足Redis對(duì)字符串在功能、效率、安全等方面的需求。故其內(nèi)部設(shè)計(jì)了一種名為SDS簡(jiǎn)單動(dòng)態(tài)字符串的數(shù)據(jù)結(jié)構(gòu)以用于存儲(chǔ)字符串。簡(jiǎn)單來說相比較于C字符串而言,SDS具有以下幾個(gè)方面的優(yōu)點(diǎn)

          1. 避免緩沖區(qū)溢出
          2. 減少修改字符串帶來的內(nèi)存重分配次數(shù)。一方面,通過預(yù)分配內(nèi)存空間來應(yīng)對(duì)SDS的字符串的未來增長(zhǎng);另一方面,通過內(nèi)存空間的惰性釋放應(yīng)對(duì)SDS的字符串的縮短操作
          3. 二進(jìn)制安全:在C的字符數(shù)組中,對(duì)于空字符(即\0)會(huì)視為字符串的結(jié)尾。故其不能保存類似于圖像、音頻等的二進(jìn)制數(shù)據(jù)。而在SDS由于采用了單獨(dú)的屬性字段表示SDS的字符串長(zhǎng)度,故使得其可以保存二進(jìn)制數(shù)據(jù)
          4. 由于SDS采用了單獨(dú)的屬性字段表示SDS的字符串長(zhǎng)度,故可以以常數(shù)時(shí)間復(fù)雜度獲取SDS的字符串長(zhǎng)度

          linkedlist 雙向鏈表

          Redis的雙向鏈表存在如下特點(diǎn)

          1. 內(nèi)置了head表頭、tail表尾字段,可以快速定位到鏈表的表頭、表尾
          2. 表頭所指向的節(jié)點(diǎn)的前驅(qū)指針、表尾所指向的節(jié)點(diǎn)的后繼指針 均指向 NULL,故在該雙向鏈表中是不存在環(huán)的
          3. 內(nèi)置了鏈表長(zhǎng)度計(jì)數(shù)器字段,故可以以常數(shù)時(shí)間復(fù)雜度獲取鏈表中元素的數(shù)量

          dict 字典

          在Redis的dict字典是通過哈希表(注意,此處的哈希表不是指Redis對(duì)外所提供的Hash哈希數(shù)據(jù)類型)作為底層實(shí)現(xiàn)的。其中每個(gè)字典內(nèi)部實(shí)際上是帶有兩個(gè)哈希表的,第二個(gè)哈希表僅在rehash重哈希時(shí)用于臨時(shí)存儲(chǔ)鍵值對(duì)。值得一提的是,rehash重哈希過程并不是一次性、集中式地完成,而是分多次、漸進(jìn)式地完成。以避免鍵值對(duì)數(shù)量過多、龐大的計(jì)算量對(duì)Redis 服務(wù)端性能造成影響。這樣在rehash重哈希完成之前,如果對(duì)字典進(jìn)行查詢、刪除等操作,就必須同時(shí)使用兩個(gè)哈希表。例如對(duì)于查詢操作而言,當(dāng)?shù)谝粋€(gè)哈希表中不存在相應(yīng)鍵時(shí),就需要去第二個(gè)哈希表進(jìn)行查找。而對(duì)于哈希沖突,則采用鏈地址法。這樣同一個(gè)索引下的多個(gè)鍵值對(duì)會(huì)形成一個(gè)單向鏈表

          skiplist 跳表

          Redis中的skiplist跳表是Zset有序集合的實(shí)現(xiàn)方式之一。不同于一般的跳表,為了方便Zset計(jì)算元素排名Rank的需求。其在跳表節(jié)點(diǎn)的每一層中提供了一個(gè)跨度的屬性(即level[i].span屬性),以用于表示在當(dāng)前層中從前一個(gè)跳表節(jié)點(diǎn)到當(dāng)前跳表節(jié)點(diǎn)所經(jīng)過的節(jié)點(diǎn)數(shù)。這樣在查找某個(gè)元素的過程中,只需將沿途訪問過的所有層的跨度累計(jì)起來。就可以得到目標(biāo)元素在跳表中的排名

          ziplist 壓縮列表

          ziplist壓縮列表是Redis為了節(jié)約內(nèi)存而開發(fā)的由連續(xù)內(nèi)存組成的順序型數(shù)據(jù)結(jié)構(gòu)。由于列表中各節(jié)點(diǎn)所使用的內(nèi)存是連續(xù)分配的,故在列表頭部的內(nèi)存空間只需記錄表尾距離列表的偏移量即可確定表尾的位置;同理,在每個(gè)列表節(jié)點(diǎn)中只需記錄前一個(gè)節(jié)點(diǎn)所使用的字節(jié)數(shù),即可快速定位的前一個(gè)節(jié)點(diǎn)。換言之,壓縮列表也是雙向的。同樣由于內(nèi)存分配是連續(xù)的,故新增、修改、刪除節(jié)點(diǎn)會(huì)引發(fā)列表的連鎖更新

          過期刪除機(jī)制

          實(shí)現(xiàn)原理

          客戶端無論通過何種命令(EXPIRE、PEXPIRE、EXPIREAT、PEXPIREAT等命令)設(shè)置Key的TTL,Redis服務(wù)端最終都會(huì)將其轉(zhuǎn)化為絕對(duì)等到期時(shí)間的毫秒級(jí)Unix時(shí)間戳進(jìn)行存儲(chǔ),即最終都是通過PEXPIREAT命令實(shí)現(xiàn)的。例如當(dāng)前時(shí)間為2022年4月17日零時(shí),那么我們?cè)O(shè)置Key的生存時(shí)間為10天。則該Redis服務(wù)端會(huì)將2022年4月27日零時(shí)所對(duì)應(yīng)的毫秒級(jí)Unix時(shí)間戳存儲(chǔ)、記錄下來

          至于Redis對(duì)過期Key的刪除會(huì)同時(shí)采用兩種策略:

          • 「惰性刪除」:每次執(zhí)行Redis命令前都會(huì)對(duì)Key進(jìn)行檢查,判斷Key是否存在、是否過期。如果Key存在 且 Key已過期,則會(huì)刪除該Key;如果Key存在 且 未過期,則繼續(xù)執(zhí)行命令
          • 「定期刪除」:Redis內(nèi)部會(huì)有一個(gè)定時(shí)任務(wù),每次執(zhí)行任務(wù)時(shí)會(huì)在指定時(shí)間范圍內(nèi)對(duì)一定數(shù)量的數(shù)據(jù)庫(kù)中隨機(jī)抽取一定數(shù)量的設(shè)置了過期時(shí)間的Key進(jìn)行檢查。當(dāng)檢查發(fā)現(xiàn)某個(gè)設(shè)置了過期時(shí)間的Key已經(jīng)過期則會(huì)進(jìn)行刪除

          從Redis 服務(wù)端的角度來看,惰性刪除對(duì)于Redis服務(wù)端來說是被動(dòng)刪除策略,定期刪除對(duì)于Redis服務(wù)端來說是主動(dòng)刪除策略。之所以同時(shí)采用兩種策略。是因?yàn)閮H僅使用前者的話,一旦Key過期后,如果客戶端沒有再次訪問該Key、發(fā)起對(duì)該Key的命令,則該Key將永遠(yuǎn)無法被刪除。長(zhǎng)久以往會(huì)大大浪費(fèi)Redis的內(nèi)存空間,嚴(yán)重時(shí)甚至可以視為內(nèi)存泄露。故其還需要定期刪除策略對(duì)其進(jìn)行兜底;而僅僅使用后者的話,為了避免定期任務(wù)在刪除過期Key占用過多的CPU時(shí)間,而導(dǎo)致影響Redis服務(wù)器對(duì)客戶端命令的響應(yīng)時(shí)間、吞吐量。故定期任務(wù)每次只會(huì)刪除一定數(shù)量的部分過期Key。一旦某個(gè)過期Key沒有來得及被定期任務(wù)刪除、而恰好又被客戶端再一次訪問時(shí),即會(huì)導(dǎo)致客戶端產(chǎn)生該Key未過期的錯(cuò)覺。故其還需要惰性刪除策略對(duì)其進(jìn)行兜底

          RDB對(duì)過期Key處理策略

          「1. 生成RDB文件階段」

          在通過save、bgsave命令創(chuàng)建一個(gè)新的RDB文件時(shí),其會(huì)對(duì)數(shù)據(jù)庫(kù)中的Key進(jìn)行檢查。以保證過期Key不會(huì)被保存到新創(chuàng)建的REB文件中

          「2. 載入RDB文件階段」

          在Redis啟動(dòng)過程中如果開啟了RDB功能,則其會(huì)對(duì)RDB文件進(jìn)行載入。具體地:

          • 如果Redis不是以Slave身份運(yùn)行,則在載入過程中其會(huì)對(duì)RDB文件中的Key進(jìn)行檢查。以保證未過期的Key會(huì)被載入,而過期Key則會(huì)被直接忽略、不會(huì)載入到數(shù)據(jù)庫(kù)中
          • 如果Redis是以Slave身份運(yùn)行,則對(duì)于RDB文件中的所有Key。無論是否過期,都會(huì)被載入到數(shù)據(jù)庫(kù)中。但因?yàn)镸aster、Slave在進(jìn)行同步時(shí),從庫(kù)會(huì)被清空,故一般來說,過期Key對(duì)載入RDB文件的Slave而言也不會(huì)產(chǎn)生什么影響

          AOF對(duì)過期KEY處理策略

          「1. AOF文件追加、寫入、同步」

          當(dāng)Redis以AOF方式進(jìn)行持久化時(shí),在新增Key時(shí)會(huì)向AOF文件追加一條新增命令。當(dāng)Key過期后通過惰性刪除、定期刪除機(jī)制被刪除后,其會(huì)再次向AOF追加一條DEL刪除命令。即顯式地記錄該過期Key已被刪除

          「2. AOF重寫」

          在進(jìn)行AOF重寫過程中,其與生成RDB文件類似。同樣會(huì)對(duì)數(shù)據(jù)庫(kù)中的Key進(jìn)行檢查。以保證過期Key不會(huì)被保存到重寫后的AOF文件中

          Replication對(duì)過期KEY處理策略

          當(dāng)Redis運(yùn)行在復(fù)制模式下,Slave中過期Key的刪除是由Master進(jìn)行控制的。以此保證Master-Slave 數(shù)據(jù)的一致性。具體地

          1. Master在刪除一個(gè)過期Key后,會(huì)顯式向所有Slave發(fā)送一個(gè)DEL命令。以用于告知Slave刪除這個(gè)過期Key
          2. Slave在接收到Master發(fā)送的DEL命令前,即使Key過期了Slave也不會(huì)將其刪除。換言之,此時(shí)客戶端如果訪問該過期Key,依然可以正常獲取相應(yīng)的數(shù)據(jù),就像這個(gè)Key還未過期一樣
          3. Slave在接收到Master發(fā)送的DEL命令后,Slave才會(huì)將相應(yīng)的過期Key刪除

          持久化

          RDB

          「1. 創(chuàng)建RDB文件」

          RDB(Redis DataBase)方式的持久化實(shí)際上是將在某個(gè)時(shí)間點(diǎn)的數(shù)據(jù)庫(kù)快照保存在名為dump.rdb的文件當(dāng)中??赏ㄟ^save、bgsave命令手動(dòng)顯式地創(chuàng)建RDB文件。區(qū)別在于前者會(huì)阻塞Redis服務(wù)端進(jìn)程,直到RDB文件創(chuàng)建完成為止。在此之前服務(wù)端將無法處理客戶端的命令、請(qǐng)求;而后者則會(huì)創(chuàng)建一個(gè)子進(jìn)程負(fù)責(zé)創(chuàng)建RDB文件,此舉可以保證服務(wù)端能夠繼續(xù)處理客戶端的命令、請(qǐng)求

          此外Redis支持在服務(wù)端配置文件中通過添加save配置項(xiàng),來設(shè)置任意個(gè)創(chuàng)建RDB文件的條件。只要其中任意一個(gè)條件滿足,服務(wù)端即可自動(dòng)執(zhí)行bgsave命令。配置示例如下所示

          # 在900秒內(nèi) 對(duì)數(shù)據(jù)庫(kù)進(jìn)行了至少1次的修改
          save 900 1
          # 在300秒內(nèi) 對(duì)數(shù)據(jù)庫(kù)進(jìn)行了至少10次的修改
          save 300 10
          # 在60秒內(nèi) 對(duì)數(shù)據(jù)庫(kù)進(jìn)行了至少10000次的修改
          save 60 1000

          對(duì)于RDB文件,可以通過Linux命令od進(jìn)行分析。效果如下所示,其中-c、-x分別表示使用ASCII、十六進(jìn)制格式顯示文件內(nèi)容

          figure 6.jpeg

          「2. 載入RDB文件」

          RDB文件的載入是在Redis服務(wù)端啟動(dòng)時(shí)自動(dòng)完成的,故Redis未提供相應(yīng)命令。服務(wù)端在啟動(dòng)過程中只要檢測(cè)到RDB文件存在,則其就會(huì)自動(dòng)載入RDB文件。但值得一提的是,由于RDB文件相比較于下面介紹的AOF文件而言,其更新頻率低。故當(dāng)Redis服務(wù)端開啟了AOF持久化,則服務(wù)端會(huì)優(yōu)先使用AOF文件來還原數(shù)據(jù)庫(kù)狀態(tài)。只有AOF持久化在關(guān)閉的條件下,服務(wù)端才會(huì)使用RDB文件來還原數(shù)據(jù)庫(kù)

          AOF

          AOF(Append Of File)方式的持久化則是通過記錄Redis服務(wù)端執(zhí)行的寫命令來實(shí)現(xiàn)的。是否啟用AOF持久化可通過設(shè)置服務(wù)端配置文件的「appendonly」配置項(xiàng)進(jìn)行控制,該配置項(xiàng)默認(rèn)為no,即不啟用AOF持久化。如果為yes則表示啟用AOF持久化

          「1. AOF文件追加、寫入、同步」

          在AOF持久化的基本原理,包括三個(gè)步驟:追加命令、文件寫入、文件同步。當(dāng)開啟AOF持久化后,服務(wù)端在執(zhí)行完一個(gè)寫命令后,會(huì)以指定格式將被執(zhí)行的命令追加寫入Redis的AOF緩沖區(qū)。然后將AOF緩沖區(qū)寫入、同步至AOF文件當(dāng)中。這里之所以將寫入、同步視為兩個(gè)步驟。是因?yàn)楝F(xiàn)代操作系統(tǒng)為了提高寫入效率,把數(shù)據(jù)從內(nèi)存寫到硬盤分為兩個(gè)步驟:先將內(nèi)存數(shù)據(jù)寫入內(nèi)存緩沖區(qū),待內(nèi)存緩沖區(qū)滿了 或 達(dá)到時(shí)限后,再真正將內(nèi)存緩沖區(qū)的數(shù)據(jù)寫入磁盤。此舉雖然提高了效率,但也帶來一定的風(fēng)險(xiǎn)。因?yàn)槿绻麅?nèi)存緩沖區(qū)的數(shù)據(jù)還未來得及寫入磁盤,計(jì)算機(jī)發(fā)生宕機(jī)。即會(huì)出現(xiàn)數(shù)據(jù)丟失的風(fēng)險(xiǎn)

          為此Redis服務(wù)端的配置文件提供了一個(gè)「appendfsync」參數(shù),用于控制文件寫入、文件同步的時(shí)機(jī)

          • 「always」:將AOF緩沖區(qū)的所有內(nèi)容寫入并同步到AOF文件。該配置顯然效率最低、但安全性高
          • 「everysec」:將AOF緩沖區(qū)的所有內(nèi)容寫入到AOF文件;如果距離上次文件同步超過1秒,則會(huì)再次進(jìn)行同步。其是appendfsync配置項(xiàng)的默認(rèn)值。因?yàn)樾?、安全各方面表現(xiàn)比較均衡。即使Redis發(fā)生意外宕機(jī),也只會(huì)丟失1秒鐘的命令數(shù)據(jù)
          • 「no」:將AOF緩沖區(qū)的所有內(nèi)容寫入到AOF文件,但不對(duì)AOF文件進(jìn)行同步。何時(shí)同步交由操作系統(tǒng)控制、決定。顯然安全性最差

          「2. AOF重寫」

          隨著Redis運(yùn)行時(shí)間越來越長(zhǎng),AOF文件存在文件體積膨脹的問題。比如我們先每次向list添加一個(gè)隨機(jī)數(shù)、然后添加100次后,再每次隨機(jī)從list刪除一個(gè)數(shù),直到list中只剩一個(gè)元素為止。那么AOF文件中為了記錄這個(gè)list的數(shù)據(jù)狀態(tài),就已經(jīng)記錄、寫入了199條命令。而實(shí)際上list中卻只有一個(gè)元素。為此Redis中引入了AOF rewrite重寫機(jī)制,以重新生成一個(gè)新的AOF文件以替代原來較大的AOF文件。重寫后的AOF文件由于不存在冗余命令,故文件體積將會(huì)大幅縮減

          AOF重寫機(jī)制的實(shí)現(xiàn)也很簡(jiǎn)單,其會(huì)直接讀取Redis數(shù)據(jù)庫(kù)中的鍵值對(duì)來實(shí)現(xiàn),而無需對(duì)原AOF文件進(jìn)行讀取、分析操作。例如對(duì)于上面的例子,只需 「向該list添加最后僅剩的一個(gè)元素」 這1條命令即可表示。同時(shí)為避免在AOF重寫過程中阻塞Redis服務(wù)端進(jìn)程、進(jìn)而無法處理客戶端的命令、請(qǐng)求,其會(huì)創(chuàng)建一個(gè)子進(jìn)程用于進(jìn)行AOF重寫。以保證服務(wù)端能夠繼續(xù)處理客戶端的命令、請(qǐng)求

          由于在AOF重寫期間,Redis服務(wù)端接收到客戶端新的命令可能會(huì)對(duì)現(xiàn)有數(shù)據(jù)庫(kù)狀態(tài)進(jìn)行修改,進(jìn)而使得Redis最新的數(shù)據(jù)庫(kù)狀態(tài)與重寫后的AOF文件不一致。為了解決這一問題,Redis設(shè)置了一個(gè)AOF重寫緩沖區(qū)。在AOF重寫期間,當(dāng)服務(wù)端進(jìn)程在執(zhí)行完客戶端發(fā)送的寫命令后,會(huì)分別將該命令追加到AOF緩沖區(qū)、AOF重寫緩沖區(qū)。這樣當(dāng)子進(jìn)程完成AOF重寫工作后,再把AOF重寫緩沖區(qū)中的內(nèi)容追加、寫入到AOF重寫文件中。最后對(duì)重寫AOF文件進(jìn)行改名,覆蓋替換掉原來的AOF文件。這樣整個(gè)AOF重寫就完成了

          「3. 載入AOF文件」

          由于AOF文件中包含了恢復(fù)數(shù)據(jù)庫(kù)所需的全部寫命令,故服務(wù)端只需讀入并重新執(zhí)行一遍AOF文件中的寫命令即可。值得一提的是,Redis服務(wù)端在載入AOF文件時(shí)會(huì)創(chuàng)建一個(gè)不帶網(wǎng)絡(luò)連接的偽客戶端,以用于發(fā)起調(diào)用寫命令的請(qǐng)求。當(dāng)AOF文件載入完畢后,會(huì)關(guān)閉這個(gè)偽客戶端

          參考文獻(xiàn)

          1. Redis設(shè)計(jì)與實(shí)現(xiàn) 黃健宏著


          瀏覽 31
          點(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>
                  黄片在线免费视频 | 大屌操视频在线 | 人人草人人爱 | 熟女18p | 亚洲免费观看视频 |