<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # RDB [TOC=2,3] 在運行情況下,Redis 以數據結構的形式將數據維持在內存中,為了讓這些數據在 Redis 重啟之后仍然可用,Redis 分別提供了 RDB 和 AOF 兩種[持久化](http://en.wikipedia.org/wiki/Persistence_\(computer_science\)) 模式。 在 Redis 運行時,RDB 程序將當前內存中的數據庫快照保存到磁盤文件中,在 Redis 重啟動時,RDB 程序可以通過載入 RDB 文件來還原數據庫的狀態。 RDB 功能最核心的是 `rdbSave` 和 `rdbLoad` 兩個函數,前者用于生成 RDB 文件到磁盤,而后者則用于將 RDB 文件中的數據重新載入到內存中: ![digraph persistent { rankdir = LR; node [shape = circle, style = filled]; edge [style = bold]; redis_object [label = "內存中的\n數據對象", fillcolor = "#A8E270"]; rdb [label = "磁盤中的\nRDB文件", fillcolor = "#95BBE3"]; redis_object -> rdb [label = "rdbSave"]; rdb -> redis_object [label = "rdbLoad"];}](https://box.kancloud.cn/2015-09-13_55f4effe6ade7.svg) 本章先介紹 [SAVE](http://redis.readthedocs.org/en/latest/server/save.html#save "(in Redis 命令參考 v2.8)") 和 [BGSAVE](http://redis.readthedocs.org/en/latest/server/bgsave.html#bgsave "(in Redis 命令參考 v2.8)") 命令的實現,以及 `rdbSave` 和 `rdbLoad` 兩個函數的運行機制,然后以圖表的方式,分部分來介紹 RDB 文件的組織形式。 因為本章涉及 RDB 運行的相關機制,如果還沒了解過 RDB 功能的話,請先閱讀 [Redis 官網上的 persistence 手冊](http://redis.io/topics/persistence) 。 ### 保存 `rdbSave` 函數負責將內存中的數據庫數據以 RDB 格式保存到磁盤中,如果 RDB 文件已存在,那么新的 RDB 文件將替換已有的 RDB 文件。 在保存 RDB 文件期間,主進程會被阻塞,直到保存完成為止。 [SAVE](http://redis.readthedocs.org/en/latest/server/save.html#save "(in Redis 命令參考 v2.8)") 和 [BGSAVE](http://redis.readthedocs.org/en/latest/server/bgsave.html#bgsave "(in Redis 命令參考 v2.8)") 兩個命令都會調用 `rdbSave` 函數,但它們調用的方式各有不同: - [SAVE](http://redis.readthedocs.org/en/latest/server/save.html#save "(in Redis 命令參考 v2.8)") 直接調用 `rdbSave` ,阻塞 Redis 主進程,直到保存完成為止。在主進程阻塞期間,服務器不能處理客戶端的任何請求。 - [BGSAVE](http://redis.readthedocs.org/en/latest/server/bgsave.html#bgsave "(in Redis 命令參考 v2.8)") 則 `fork` 出一個子進程,子進程負責調用 `rdbSave` ,并在保存完成之后向主進程發送信號,通知保存已完成。因為 `rdbSave` 在子進程被調用,所以 Redis 服務器在 [BGSAVE](http://redis.readthedocs.org/en/latest/server/bgsave.html#bgsave "(in Redis 命令參考 v2.8)") 執行期間仍然可以繼續處理客戶端的請求。 通過偽代碼來描述這兩個命令,可以很容易地看出它們之間的區別: ~~~ def SAVE(): rdbSave() def BGSAVE(): pid = fork() if pid == 0: # 子進程保存 RDB rdbSave() elif pid > 0: # 父進程繼續處理請求,并等待子進程的完成信號 handle_request() else: # pid == -1 # 處理 fork 錯誤 handle_fork_error() ~~~ ### SAVE 、 BGSAVE 、 AOF 寫入和 BGREWRITEAOF 除了了解 RDB 文件的保存方式之外,我們可能還想知道,兩個 RDB 保存命令能否同時使用?它們和 AOF 保存工作是否沖突? 本節就來解答這些問題。 ### SAVE 前面提到過,當 [SAVE](http://redis.readthedocs.org/en/latest/server/save.html#save "(in Redis 命令參考 v2.8)") 執行時,Redis 服務器是阻塞的,所以當 [SAVE](http://redis.readthedocs.org/en/latest/server/save.html#save "(in Redis 命令參考 v2.8)") 正在執行時,新的 [SAVE](http://redis.readthedocs.org/en/latest/server/save.html#save "(in Redis 命令參考 v2.8)") 、 [BGSAVE](http://redis.readthedocs.org/en/latest/server/bgsave.html#bgsave "(in Redis 命令參考 v2.8)") 或 [BGREWRITEAOF](http://redis.readthedocs.org/en/latest/server/bgrewriteaof.html#bgrewriteaof "(in Redis 命令參考 v2.8)") 調用都不會產生任何作用。 只有在上一個 [SAVE](http://redis.readthedocs.org/en/latest/server/save.html#save "(in Redis 命令參考 v2.8)") 執行完畢、Redis 重新開始接受請求之后,新的 [SAVE](http://redis.readthedocs.org/en/latest/server/save.html#save "(in Redis 命令參考 v2.8)") 、 [BGSAVE](http://redis.readthedocs.org/en/latest/server/bgsave.html#bgsave "(in Redis 命令參考 v2.8)") 或 [BGREWRITEAOF](http://redis.readthedocs.org/en/latest/server/bgrewriteaof.html#bgrewriteaof "(in Redis 命令參考 v2.8)") 命令才會被處理。 另外,因為 AOF 寫入由后臺線程完成,而 [BGREWRITEAOF](http://redis.readthedocs.org/en/latest/server/bgrewriteaof.html#bgrewriteaof "(in Redis 命令參考 v2.8)") 則由子進程完成,所以在 [SAVE](http://redis.readthedocs.org/en/latest/server/save.html#save "(in Redis 命令參考 v2.8)") 執行的過程中,AOF 寫入和 [BGREWRITEAOF](http://redis.readthedocs.org/en/latest/server/bgrewriteaof.html#bgrewriteaof "(in Redis 命令參考 v2.8)") 可以同時進行。 ### BGSAVE 在執行 [SAVE](http://redis.readthedocs.org/en/latest/server/save.html#save "(in Redis 命令參考 v2.8)") 命令之前,服務器會檢查 [BGSAVE](http://redis.readthedocs.org/en/latest/server/bgsave.html#bgsave "(in Redis 命令參考 v2.8)") 是否正在執行當中,如果是的話,服務器就不調用 `rdbSave` ,而是向客戶端返回一個出錯信息,告知在 [BGSAVE](http://redis.readthedocs.org/en/latest/server/bgsave.html#bgsave "(in Redis 命令參考 v2.8)") 執行期間,不能執行 [SAVE](http://redis.readthedocs.org/en/latest/server/save.html#save "(in Redis 命令參考 v2.8)") 。 這樣做可以避免 [SAVE](http://redis.readthedocs.org/en/latest/server/save.html#save "(in Redis 命令參考 v2.8)") 和 [BGSAVE](http://redis.readthedocs.org/en/latest/server/bgsave.html#bgsave "(in Redis 命令參考 v2.8)") 調用的兩個 `rdbSave` 交叉執行,造成競爭條件。 另一方面,當 [BGSAVE](http://redis.readthedocs.org/en/latest/server/bgsave.html#bgsave "(in Redis 命令參考 v2.8)") 正在執行時,調用新 [BGSAVE](http://redis.readthedocs.org/en/latest/server/bgsave.html#bgsave "(in Redis 命令參考 v2.8)") 命令的客戶端會收到一個出錯信息,告知 [BGSAVE](http://redis.readthedocs.org/en/latest/server/bgsave.html#bgsave "(in Redis 命令參考 v2.8)") 已經在執行當中。 [BGREWRITEAOF](http://redis.readthedocs.org/en/latest/server/bgrewriteaof.html#bgrewriteaof "(in Redis 命令參考 v2.8)") 和 [BGSAVE](http://redis.readthedocs.org/en/latest/server/bgsave.html#bgsave "(in Redis 命令參考 v2.8)") 不能同時執行: - 如果 [BGSAVE](http://redis.readthedocs.org/en/latest/server/bgsave.html#bgsave "(in Redis 命令參考 v2.8)") 正在執行,那么 [BGREWRITEAOF](http://redis.readthedocs.org/en/latest/server/bgrewriteaof.html#bgrewriteaof "(in Redis 命令參考 v2.8)") 的重寫請求會被延遲到 [BGSAVE](http://redis.readthedocs.org/en/latest/server/bgsave.html#bgsave "(in Redis 命令參考 v2.8)") 執行完畢之后進行,執行 [BGREWRITEAOF](http://redis.readthedocs.org/en/latest/server/bgrewriteaof.html#bgrewriteaof "(in Redis 命令參考 v2.8)") 命令的客戶端會收到請求被延遲的回復。 - 如果 [BGREWRITEAOF](http://redis.readthedocs.org/en/latest/server/bgrewriteaof.html#bgrewriteaof "(in Redis 命令參考 v2.8)") 正在執行,那么調用 [BGSAVE](http://redis.readthedocs.org/en/latest/server/bgsave.html#bgsave "(in Redis 命令參考 v2.8)") 的客戶端將收到出錯信息,表示這兩個命令不能同時執行。 [BGREWRITEAOF](http://redis.readthedocs.org/en/latest/server/bgrewriteaof.html#bgrewriteaof "(in Redis 命令參考 v2.8)") 和 [BGSAVE](http://redis.readthedocs.org/en/latest/server/bgsave.html#bgsave "(in Redis 命令參考 v2.8)") 兩個命令在操作方面并沒有什么沖突的地方,不能同時執行它們只是一個性能方面的考慮:并發出兩個子進程,并且兩個子進程都同時進行大量的磁盤寫入操作,這怎么想都不會是一個好主意。 ### 載入 當 Redis 服務器啟動時,`rdbLoad` 函數就會被執行,它讀取 RDB 文件,并將文件中的數據庫數據載入到內存中。 在載入期間,服務器每載入 1000 個鍵就處理一次所有已到達的請求,不過只有 `PUBLISH` 、 `SUBSCRIBE` 、 `PSUBSCRIBE` 、 `UNSUBSCRIBE` 、 `PUNSUBSCRIBE` 五個命令的請求會被正確地處理,其他命令一律返回錯誤。等到載入完成之后,服務器才會開始正常處理所有命令。 Note 發布與訂閱功能和其他數據庫功能是完全隔離的,前者不寫入也不讀取數據庫,所以在服務器載入期間,訂閱與發布功能仍然可以正常使用,而不必擔心對載入數據的完整性產生影響。 另外,因為 AOF 文件的保存頻率通常要高于 RDB 文件保存的頻率,所以一般來說,AOF 文件中的數據會比 RDB 文件中的數據要新。 因此,如果服務器在啟動時,打開了 AOF 功能,那么程序優先使用 AOF 文件來還原數據。只有在 AOF 功能未打開的情況下,Redis 才會使用 RDB 文件來還原數據。 ### RDB 文件結構 前面介紹了保存和讀取 RDB 文件的兩個函數,現在,是時候介紹 RDB 文件本身了。 一個 RDB 文件可以分為以下幾個部分: ~~~ +-------+-------------+-----------+-----------------+-----+-----------+ | REDIS | RDB-VERSION | SELECT-DB | KEY-VALUE-PAIRS | EOF | CHECK-SUM | +-------+-------------+-----------+-----------------+-----+-----------+ |<-------- DB-DATA ---------->| ~~~ 以下的幾個小節將分別對這幾個部分的保存和讀入規則進行介紹。 ### REDIS 文件的最開頭保存著 `REDIS` 五個字符,標識著一個 RDB 文件的開始。 在讀入文件的時候,程序可以通過檢查一個文件的前五個字節,來快速地判斷該文件是否有可能是 RDB 文件。 ### RDB-VERSION 一個四字節長的以字符表示的整數,記錄了該文件所使用的 RDB 版本號。 目前的 RDB 文件版本為 `0006` 。 因為不同版本的 RDB 文件互不兼容,所以在讀入程序時,需要根據版本來選擇不同的讀入方式。 ### DB-DATA 這個部分在一個 RDB 文件中會出現任意多次,每個 `DB-DATA` 部分保存著服務器上一個非空數據庫的所有數據。 ### SELECT-DB 這域保存著跟在后面的鍵值對所屬的數據庫號碼。 在讀入 RDB 文件時,程序會根據這個域的值來切換數據庫,確保數據被還原到正確的數據庫上。 ### KEY-VALUE-PAIRS 因為空的數據庫不會被保存到 RDB 文件,所以這個部分至少會包含一個鍵值對的數據。 每個鍵值對的數據使用以下結構來保存: ~~~ +----------------------+---------------+-----+-------+ | OPTIONAL-EXPIRE-TIME | TYPE-OF-VALUE | KEY | VALUE | +----------------------+---------------+-----+-------+ ~~~ `OPTIONAL-EXPIRE-TIME` 域是可選的,如果鍵沒有設置過期時間,那么這個域就不會出現;反之,如果這個域出現的話,那么它記錄著鍵的過期時間,在當前版本的 RDB 中,過期時間是一個以毫秒為單位的 UNIX 時間戳。 `KEY` 域保存著鍵,格式和 `REDIS_ENCODING_RAW` 編碼的字符串對象一樣(見下文)。 `TYPE-OF-VALUE` 域記錄著 `VALUE` 域的值所使用的編碼,根據這個域的指示,程序會使用不同的方式來保存和讀取 `VALUE` 的值。 Note 下文提到的編碼在《[對象處理機制](#)》章節介紹過,如果忘記了可以回去重溫下。 保存 `VALUE` 的詳細格式如下: - `REDIS_ENCODING_INT` 編碼的 `REDIS_STRING` 類型對象: 如果值可以表示為 `8` 位、 `16` 位或 `32` 位有符號整數,那么直接以整數類型的形式來保存它們: ~~~ +---------+ | integer | +---------+ ~~~ 比如說,整數 `8` 可以用 `8` 位序列 `00001000` 保存。 當讀入這類值時,程序按指定的長度讀入字節數據,然后將數據轉換回整數類型。 另一方面,如果值不能被表示為最高 `32` 位的有符號整數,那么說明這是一個 `long long` 類型的值,在 RDB 文件中,這種類型的值以字符序列的形式保存。 一個字符序列由兩部分組成: ~~~ +-----+---------+ | LEN | CONTENT | +-----+---------+ ~~~ 其中, `CONTENT` 域保存了字符內容,而 `LEN` 則保存了以字節為單位的字符長度。 當進行載入時,讀入器先讀入 `LEN` ,創建一個長度等于 `LEN` 的字符串對象,然后再從文件中讀取 `LEN` 字節數據,并將這些數據設置為字符串對象的值。 - `REDIS_ENCODING_RAW` 編碼的 `REDIS_STRING` 類型值有三種保存方式: 1. 如果值可以表示為 `8` 位、 `16` 位或 `32` 位長的有符號整數,那么用整數類型的形式來保存它們。 1. 如果字符串長度大于 `20` ,并且服務器開啟了 [LZF 壓縮功能](http://oldhome.schmorp.de/marc/liblzf.html) ,那么對字符串進行壓縮,并保存壓縮之后的數據。 經過 LZF 壓縮的字符串會被保存為以下結構: ~~~ +----------+----------------+--------------------+ | LZF-FLAG | COMPRESSED-LEN | COMPRESSED-CONTENT | +----------+----------------+--------------------+ ~~~ `LZF-FLAG` 告知讀入器,后面跟著的是被 LZF 算法壓縮過的數據。 `COMPRESSED-CONTENT` 是被壓縮后的數據, `COMPRESSED-LEN` 則是該數據的字節長度。 1. 在其他情況下,程序直接以普通字節序列的方式來保存字符串。比如說,對于一個長度為 `20` 字節的字符串,需要使用 `20` 字節的空間來保存它。 這種字符串被保存為以下結構: ~~~ +-----+---------+ | LEN | CONTENT | +-----+---------+ ~~~ `LEN` 為字符串的字節長度, `CONTENT` 為字符串。 當進行載入時,讀入器先檢測字符串保存的方式,再根據不同的保存方式,用不同的方法取出內容,并將內容保存到新建的字符串對象當中。 - `REDIS_ENCODING_LINKEDLIST` 編碼的 `REDIS_LIST` 類型值保存為以下結構: ~~~ +-----------+--------------+--------------+-----+--------------+ | NODE-SIZE | NODE-VALUE-1 | NODE-VALUE-2 | ... | NODE-VALUE-N | +-----------+--------------+--------------+-----+--------------+ ~~~ 其中 `NODE-SIZE` 保存鏈表節點數量,后面跟著 `NODE-SIZE` 個節點值。節點值的保存方式和字符串的保存方式一樣。 當進行載入時,讀入器讀取節點的數量,創建一個新的鏈表,然后一直執行以下步驟,直到指定節點數量滿足為止: 1. 讀取字符串表示的節點值 1. 將包含節點值的新節點添加到鏈表中 - `REDIS_ENCODING_HT` 編碼的 `REDIS_SET` 類型值保存為以下結構: ~~~ +----------+-----------+-----------+-----+-----------+ | SET-SIZE | ELEMENT-1 | ELEMENT-2 | ... | ELEMENT-N | +----------+-----------+-----------+-----+-----------+ ~~~ `SET-SIZE` 記錄了集合元素的數量,后面跟著多個元素值。元素值的保存方式和字符串的保存方式一樣。 載入時,讀入器先讀入集合元素的數量 `SET-SIZE` ,再連續讀入 `SET-SIZE` 個字符串,并將這些字符串作為新元素添加至新創建的集合。 - `REDIS_ENCODING_SKIPLIST` 編碼的 `REDIS_ZSET` 類型值保存為以下結構: ~~~ +--------------+-------+---------+-------+---------+-----+-------+---------+ | ELEMENT-SIZE | MEB-1 | SCORE-1 | MEB-2 | SCORE-2 | ... | MEB-N | SCORE-N | +--------------+-------+---------+-------+---------+-----+-------+---------+ ~~~ 其中 `ELEMENT-SIZE` 為有序集元素的數量, `MEB-i` 為第 `i` 個有序集元素的成員, `SCORE-i` 為第 `i` 個有序集元素的分值。 當進行載入時,讀入器讀取有序集元素數量,創建一個新的有序集,然后一直執行以下步驟,直到指定元素數量滿足為止: 1. 讀入字符串形式保存的成員 `member` 1. 讀入字符串形式保存的分值 `score` ,并將它轉換為浮點數 1. 添加 `member` 為成員、 `score` 為分值的新元素到有序集 - `REDIS_ENCODING_HT` 編碼的 `REDIS_HASH` 類型值保存為以下結構: ~~~ +-----------+-------+---------+-------+---------+-----+-------+---------+ | HASH-SIZE | KEY-1 | VALUE-1 | KEY-2 | VALUE-2 | ... | KEY-N | VALUE-N | +-----------+-------+---------+-------+---------+-----+-------+---------+ ~~~ `HASH-SIZE` 是哈希表包含的鍵值對的數量, `KEY-i` 和 `VALUE-i` 分別是哈希表的鍵和值。 載入時,程序先創建一個新的哈希表,然后讀入 `HASH-SIZE` ,再執行以下步驟 `HASH-SIZE` 次: 1. 讀入一個字符串 1. 再讀入另一個字符串 1. 將第一個讀入的字符串作為鍵,第二個讀入的字符串作為值,插入到新建立的哈希中。 - `REDIS_LIST` 類型、 `REDIS_HASH` 類型和 `REDIS_ZSET` 類型都使用了 `REDIS_ENCODING_ZIPLIST` 編碼, `ziplist` 在 RDB 中的保存方式如下: ~~~ +-----+---------+ | LEN | ZIPLIST | +-----+---------+ ~~~ 載入時,讀入器先讀入 `ziplist` 的字節長,再根據該字節長讀入數據,最后將數據還原成一個 `ziplist` 。 - `REDIS_ENCODING_INTSET` 編碼的 `REDIS_SET` 類型值保存為以下結構: ~~~ +-----+--------+ | LEN | INTSET | +-----+--------+ ~~~ 載入時,讀入器先讀入 `intset` 的字節長度,再根據長度讀入數據,最后將數據還原成 `intset` 。 ### EOF 標志著數據庫內容的結尾(不是文件的結尾),值為 `rdb.h/EDIS_RDB_OPCODE_EOF` (`255`)。 ### CHECK-SUM RDB 文件所有內容的校驗和,一個 `uint_64t` 類型值。 REDIS 在寫入 RDB 文件時將校驗和保存在 RDB 文件的末尾,當讀取時,根據它的值對內容進行校驗。 如果這個域的值為 `0` ,那么表示 Redis 關閉了校驗和功能。 ### 小結 - `rdbSave` 會將數據庫數據保存到 RDB 文件,并在保存完成之前阻塞調用者。 - [SAVE](http://redis.readthedocs.org/en/latest/server/save.html#save "(in Redis 命令參考 v2.8)") 命令直接調用 `rdbSave` ,阻塞 Redis 主進程; [BGSAVE](http://redis.readthedocs.org/en/latest/server/bgsave.html#bgsave "(in Redis 命令參考 v2.8)") 用子進程調用 `rdbSave` ,主進程仍可繼續處理命令請求。 - [SAVE](http://redis.readthedocs.org/en/latest/server/save.html#save "(in Redis 命令參考 v2.8)") 執行期間, AOF 寫入可以在后臺線程進行, [BGREWRITEAOF](http://redis.readthedocs.org/en/latest/server/bgrewriteaof.html#bgrewriteaof "(in Redis 命令參考 v2.8)") 可以在子進程進行,所以這三種操作可以同時進行。 - 為了避免產生競爭條件, [BGSAVE](http://redis.readthedocs.org/en/latest/server/bgsave.html#bgsave "(in Redis 命令參考 v2.8)") 執行時, [SAVE](http://redis.readthedocs.org/en/latest/server/save.html#save "(in Redis 命令參考 v2.8)") 命令不能執行。 - 為了避免性能問題, [BGSAVE](http://redis.readthedocs.org/en/latest/server/bgsave.html#bgsave "(in Redis 命令參考 v2.8)") 和 [BGREWRITEAOF](http://redis.readthedocs.org/en/latest/server/bgrewriteaof.html#bgrewriteaof "(in Redis 命令參考 v2.8)") 不能同時執行。 - 調用 `rdbLoad` 函數載入 RDB 文件時,不能進行任何和數據庫相關的操作,不過訂閱與發布方面的命令可以正常執行,因為它們和數據庫不相關聯。 - RDB 文件的組織方式如下: ~~~ +-------+-------------+-----------+-----------------+-----+-----------+ | REDIS | RDB-VERSION | SELECT-DB | KEY-VALUE-PAIRS | EOF | CHECK-SUM | +-------+-------------+-----------+-----------------+-----+-----------+ |<-------- DB-DATA ---------->| ~~~ - 鍵值對在 RDB 文件中的組織方式如下: ~~~ +----------------------+---------------+-----+-------+ | OPTIONAL-EXPIRE-TIME | TYPE-OF-VALUE | KEY | VALUE | +----------------------+---------------+-----+-------+ ~~~ RDB 文件使用不同的格式來保存不同類型的值。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看