精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

別造輪子了,先來“抄”一下 RocketMQ 的文件編程藝術

開發 前端
學習 RocketMQ,我們學的不僅是 “術”(具體的實現技巧),更是 “道”(解決問題的思想和方法論)。希望通過本文的剖析,能為你打開一扇通往高性能存儲世界的大門,并在未來的系統設計中,能夠更加游刃有余地運用這些閃耀著智慧光芒的編程藝術。?

最近有朋友問我,如何從零開始設計一套高性能、高可靠、且支持快速查詢的文件存儲系統?

這是一個典型的后端面試高頻題,也是一個極具挑戰的真實工程難題。我的回答是:與其閉門造車,不如站在巨人的肩膀上——去“抄”一個頂級的開源實現。

他追問:“抄誰?”

我說:“當然是抄 RocketMQ!它在文件處理上的設計,堪稱 Java 領域的教科書,充滿了工程的智慧與藝術。無論是海量消息的順序寫入,還是高效的索引查詢,亦或是對內存和磁盤的極致運用,RocketMQ 的每一處細節都值得我們細細品味。下面,就讓我們一同深入這座寶庫,探索其背后的文件編程藝術。”

消息存儲格式看文件編程

commitlog 文件設計:學習文件編程的起點

我們知道,RocketMQ 的全量消息均存儲在 commitlog 文件中。由于每條消息的大小不一,我們面臨第一個挑戰:如何高效地組織這些消息,以便在讀取時能夠準確地區分每條消息的邊界?

在基于文件的編程模型中,首要任務是定義一套清晰的消息存儲格式。一個通用的實踐是將數據結構設計為 Header + Body 的形式。其中,Header 部分采用定長設計,存放元數據信息;Body 部分則存放實際的數據。在 RocketMQ 的存儲協議中,我們可以將記錄消息總長度的 4 字節視為 Header,其后的所有字段則構成 Body,包含了與消息相關的業務屬性,它們共同按照預定格式組裝。

圖片圖片

對于 Header + Body 這種協議,提取一條完整消息通常分為兩步:首先,讀取定長的 Header,從中解析出 Body 的長度(在 RocketMQ 中即為消息的總長度)。然后,根據這個長度,從消息的起始位置 讀取完整的消息數據,并按照預定義的格式解析出各個業務字段。

那問題又來了,如果確定一條消息的開頭呢?難不成從文件的開始處開始遍歷?

正如關系型數據庫會為每條記錄分配一個唯一的 ID,在文件編程模型中,我們也為每條消息引入了一個關鍵的身份標識:消息物理偏移量(Physical Offset),它精確地指明了消息在文件中的起始存儲位置。

圖片圖片

因此,通過 物理偏移量 + 消息大小(SIZE) 這一組合,我們便能輕而易舉地從海量數據中精確定位并提取出任何一條完整的消息。

此外,commitlog 的文件組織還揭示了另一個通用實踐:文件通常以一個“魔數”(Magic Number)開頭,用于快速校驗文件類型和完整性。同時,在文件末尾,可能會使用特殊填充(PAD)來處理空間。例如,當文件剩余空間不足以容納一條完整的消息時,系統不會將消息拆分存儲,而是用 PAD 填充剩余部分,以保證下一條消息能從新文件的起始位置寫入,維持了消息的原子性。

consumequeue 文件設計:索引的藝術

commitlog 文件基于物理偏移量查詢消息效率極高,但若要按 Topic 進行檢索,則顯得力不從心。為了解決這一痛點,RocketMQ 精心設計了 consumequeue文件作為消費隊列索引。

圖片圖片

consumequeue 的設計極具巧思。其核心在于,每個索引條目都采用固定長度設計:8 字節的 commitlog 物理偏移量、4 字節的消息長度和 8 字節的 Tag 哈希值。這里存儲的是 Tag 的哈希值而非原始字符串,正是為了確保每個條目定長。這種設計使得consumequeue 文件可以像數組一樣,通過下標(queueOffset)進行快速隨機訪問,極大地提升了索引查詢性能。

由此可見,在高性能文件存儲設計中,為特定查詢場景構建高效的索引至關重要。而索引設計的關鍵原則之一,就是采用定長條目,從而實現類似數組的 O(1) 復雜度快速定位。

性能飛躍:內存映射與頁緩存

解決了數據存儲格式與唯一標識的問題后,下一個核心挑戰是如何提升I/O性能。在文件編程實踐中,為了便于管理和數據刪除(例如過期的消息),通常會采用固定大小的日志文件策略,將數據切分成多個大小相等的文件段。RocketMQ 的 commitlog文件夾中那些 1G 大小的文件正是這一思想的體現。

圖片圖片

采用定長文件的一個核心優勢在于,它極大地簡化了內存映射(Memory Mapping)的實現。通過內存映射技術,我們可以將磁盤文件直接映射到進程的虛擬地址空間,之后就可以像訪問內存一樣讀寫磁盤上的數據,從而繞過傳統 read/write 系統調用帶來的多次數據拷貝,顯著提升文件操作性能。

在 Java 中使用內存映射的示例代碼如下:

FileChannel fileChannel = new RandomAccessFile(this.file, "rw").getChannel();
MappedByteBuffer mappedByteBuffer = this.fileChannel.map(MapMode.READ_WRITE, 0, fileSize);

實現要點如下:

  • 首先需要通過 RandomAccessFile 構建一個文件讀寫通道 FileChannel。
  • 再通過 FileChannel 的 map 方法創建內存映射區域 MappedByteBuffer。

在 Linux 系統中,MappedByteBuffer 的背后正是強大的頁緩存(Page Cache)。Linux 會盡可能地利用空閑物理內存作為頁緩存,以緩存磁盤數據。當應用程序讀寫文件時,實際上是在與頁緩存交互。如果數據在緩存中(緩存命中),則無需磁盤 I/O;如果不在(緩存未命中),系統會觸發一個缺頁中斷,透明地將數據從磁盤加載到頁緩存中。整個過程由操作系統自動管理,對應用層開發者完全透明,極大地簡化了高性能應用的開發。

通過內存映射寫入的數據,首先會進入頁緩存,并不會立即刷寫到磁盤。持久化操作由操作系統根據其策略在后臺異步完成。這意味著,即使 Broker 進程異常崩潰,只要操作系統仍然運行,頁緩存中的數據就不會丟失,最終會被寫入磁盤,保證了一定程度的可靠性。然而,如果發生機器斷電或操作系統宕機等災難性故障,尚未從頁緩存刷入磁盤的數據將會永久丟失,這是內存映射技術需要權衡的風險。

磁盤性能提升:順序寫

要進一步壓榨磁盤性能,另一個關鍵的設計原則是使用順序寫替代隨機寫。與隨機寫相比,磁盤順序寫的性能要高出幾個數量級。這一原則在所有高性能存儲系統中都得到了廣泛應用。以大家熟悉的 MySQL InnoDB 存儲引擎為例:當執行一條更新語句時,數據首先在內存(Buffer Pool)中被修改。為了保證事務的持久性,InnoDB 并不會立即將修改后的數據頁(這會導致隨機 I/O)刷回磁盤,而是先將變更以 Redo Log 的形式順序追加到一個專用的日志文件中,并確保 Redo Log 被同步刷盤。數據文件本身的更新則可以在后臺異步、批量地進行。

圖片圖片

試想,如果沒有 Redo Log,每次更新都直接修改磁盤上的數據文件,那么更新不同表的數據就會導致磁頭在磁盤上大幅度來回尋道,產生大量的隨機 I/O,性能將慘不忍睹。通過引入 Redo Log,InnoDB 將多次離散的隨機寫操作,巧妙地轉換成了一次集中的順序寫操作,盡管多了一步寫日志的操作,但整體性能卻得到了質的飛躍。這個例子雄辯地證明了順序寫相比隨機寫的巨大優勢。

因此,在設計文件存儲模型時,一個黃金法則是:盡可能地將操作設計為順序追加(Append-Only),避免原地更新(In-Place Update)。

資源管理的智慧:引用計數器

在基于 NIO 的文件編程中,我們頻繁地與 ByteBuffer 打交道。為了在不進行數據拷貝的前提下共享緩沖區內容,slice() 方法被廣泛使用。它能創建一個與原 ByteBuffer 共享同一塊內存區域,但擁有獨立 position、limit 和 mark 指針的新 ByteBuffer。

圖片圖片

上圖 selectMappedBuffer 方法的作用,正是從一個內存映射文件(如 commitlog)的指定位置“切割”出一段數據。這種零拷貝操作雖然高效,但也引入了復雜的資源管理問題:被主 MappedByteBuffer 切割(slice)出的多個子 ByteBuffer,它們的生命周期各不相同。我們必須確保在所有子 ByteBuffer 都使用完畢之前,主 MappedByteBuffer 不能被釋放,否則將導致懸空指針和程序崩潰。

RocketMQ 如何優雅地解決這個問題呢?答案是引入引用計數器(Reference Counting)。

其核心思想是:每次調用 slice() 派生出一個新的 ByteBuffer 時,就將主對象的引用計數加一;當任何一個派生對象使用完畢被釋放時,就將引用計數減一。只有當引用計數歸零時,才真正執行底層的資源釋放操作。

圖片圖片

結合 selectMappedBuffer 方法的實現,我們可以看到:

  1. 調用 hold() 方法來增加引用計數,這標志著 MappedByteBuffer 又被“借用”了一次。
  2. 返回的 SelectMappedBufferResult 對象中封裝了派生出的 ByteBuffer。當使用者調用其 release() 方法時,內部會調用 ReferenceResource 的 release(),使引用計數減一。

可靠與性能的權衡:同步與異步刷盤

內存映射機制極大地提升了寫入性能,但其“數據先到內存,后到磁盤”的特性也帶來了新的抉擇:當 Broker 接收到消息后,是應該在數據寫入頁緩存后就向客戶端返回成功,還是必須等到數據被持久化到磁盤后才返回?

這本質上是系統性能與數據可靠性之間的權衡。為此,RocketMQ 提供了兩種持久化策略:同步刷盤和異步刷盤。

所謂的 “刷盤”,在代碼層面其實就是調用 FileChannel 或 MappedByteBuffer 的 force() 方法,強制操作系統將頁緩存中對應的數據寫入物理磁盤。

圖片圖片

同步刷盤

同步刷盤策略要求 Broker 將消息寫入內存后,必須立即將其持久化到磁盤,然后才能向客戶端返回成功響應。

但這里有一個關鍵問題:同步刷盤是每條消息都單獨刷一次盤嗎?答案是否定的。

RocketMQ 的同步刷盤實現隱藏著一個重要的優化:組提交(Group Commit)。其入口位于 GroupCommitService 類中,從類名就能看出其設計思想。

圖片圖片

實現中有兩個關鍵點:

  • 組提交:一次刷盤操作會將當前所有待刷盤的消息(一個消息組)一次性寫入磁盤,而不是一條一條地刷。這極大地減少了磁盤 I/O 次數。
  • 同步轉異步:實現上采用 CountDownLatch 將同步調用轉換為異步處理模式。主線程提交一個刷盤請求后,會限時等待 (await) 后臺刷盤線程的結果,從而實現業務邏輯的解耦。

接下來繼續探討組提交的設計理念。

圖片圖片

判斷一條刷盤請求成功的條件:當前已刷盤指針大于該條消息對應的物理偏移量,這里使用了刷盤重試機制。然后喚醒主線程并返回刷盤結果。

所謂的組提交,其核心理念理念是調用刷盤時使用的是 MappedFileQueue.flush 方法,該方法并不是只將一條消息寫入磁盤,而是會將當期未刷盤的數據一次性刷寫到磁盤,既組提交,故即使在同步刷盤情況下,也并不是每一條消息都會被執行 flush 方法,為了更直觀的展現組提交的設計理念,給出如下流程圖:

圖片圖片

異步刷盤

同步刷盤提供了最高級別的數據可靠性,但犧牲了寫入性能。考慮到 RocketMQ 的消息首先寫入 PageCache,在非極端掉電情況下數據丟失的概率很小,因此,如果業務能容忍極低概率的數據丟失以換取更高的吞吐量,可以選擇異步刷盤。

異步刷盤模式下,Broker 將消息寫入 PageCache 后會立即向客戶端返回成功,然后由一個后臺線程(FlushRealTimeService)定時將臟頁數據刷入磁盤,默認間隔為 500ms。

你可能會猜測這是用 ScheduledExecutorService 之類的定時任務實現的,但 RocketMQ 的實現更為精妙。它同樣利用了帶超時時間的 CountDownLatch.await()。這種方式的好處在于:

  • 在沒有新消息寫入時,線程會安靜地等待 500ms,避免了空輪詢帶來的 CPU 消耗。
  • 一旦有新消息寫入(wakeup() 被調用),線程會立即被喚醒執行刷盤,而無需等待 500ms 周期結束,保證了刷盤的及時性。

保障數據一致性:文件恢復機制

圖片圖片

在 RocketMQ 的架構中,commitlog 是主數據文件,而 consumequeue 和 indexFile 等索引文件是根據 commitlog 的內容異步構建的。既然是異步構建,就必然存在數據不一致的風險窗口。例如,Broker 在將數據轉發到 consumequeue 之前異常關閉,重啟后如何保證數據的一致性?

在探討恢復機制前,我們先設想幾個典型的異常場景:

  • 消息已同步刷盤到 commitlog,但在轉發到 consumequeue 之前,機器斷電。
  • 一次批量刷盤操作(例如 100MB 數據)在執行到一半(例如 50MB)時,機器斷電,導致 commitlog 文件末尾存在一條不完整的消息。
  • commitlog 刷盤成功,但在更新 checkpoint 文件(記錄各文件刷盤點)之前,進程退出。

在 RocketMQ 中,文件恢復分為正常停止和異常停止兩種場景。

兩種場景定位恢復起點的邏輯略有不同,但一旦定位到起始恢復文件,后續的文件校正思路是統一的:

  • 首先嘗試恢復 consumequeue:遍歷 consumequeue 文件,根據其定長格式(8字節偏移量 + 4字節長度 + 8字節Tag哈希碼),找到最后一條完整條目所指向的 commitlog 物理偏移量,記為 maxPhysicalOfConsumequeue。
  • 然后嘗試恢復 commitlog:遍歷 commitlog 文件,校驗魔數,并根據消息存儲格式找到最后一條完整的、校驗合格的消息,記錄其物理偏移量 physicalOffset。
  • 對比與校正:

如果 commitlog 的有效偏移量小于 consumequeue 中記錄的最大偏移量,說明 consumequeue 中存在無效的“超前”索引,需要被截斷。

如果 commitlog 的有效偏移量大于 consumequeue 中記錄的最大偏移量,說明有部分消息還未建立索引,需要從 commitlog 中重新讀取這部分消息,并重建 consumequeue 和其他索引文件。

那么,如何高效地定位到可能需要恢復的文件呢?

正常退出定位文件

在 RocketMQ 啟動時候會創建一個名為 abort 的文件,并在正常關閉時將其刪除。因此,通過檢查 abort 文件是否存在,即可判斷上次是否為異常退出。

圖片圖片

對于正常退出場景,恢復策略相對樂觀:

  • ConsumeQueue 的恢復從每個主題的第一個文件開始。
  • commitlog 的恢復從倒數第三個文件開始向后檢查。因為正常退出時,大部分文件都已完整寫入并刷盤。

異常退出定位文件

異常退出時,不確定性大大增加,恢復策略必須更加嚴謹。此時,checkpoint 文件就派上了用場。該文件記錄了 commitlog、consumequeue 等文件的最后一次刷盤時間戳。

圖片圖片

  • physicMsgTimestamp:commitlog 文件最后的刷盤的時間點
  • logicsMsgTimestamp: consumequeue 文件最后的刷盤時間點
  • indexMsgTimestamp: indexfile 文件最后的刷盤時間點

checkpoint 文件的更新總是在 commitlog 刷盤成功之后進行。

圖片圖片

這意味著 checkpoint 中記錄的刷盤點是“絕對可靠”的,早于該時間點的數據一定已經落盤。基于此,異常退出時的恢復策略是:

  • ConsumeQueue 是按照 topic 進行恢復的,從第一文件開始恢復。
  • commitlog 的恢復從最后一個文件開始,逐個向前掃描。讀取每個文件的第一條消息的存儲時間,與 checkpoint 中記錄的 physicMsgTimestamp 進行比較。一旦找到一個文件的起始時間小于等于 checkpoint 的時間戳,那么就從這個文件開始執行恢復流程。

文件恢復的入口位于 DefaultMessageStore#recover 方法,讀者可根據上述理念,自行探索源碼,定會事半功倍。

終極性能優化:Java 零拷貝

在高性能網絡文件服務中,“零拷貝”(Zero-Copy)是一個高頻詞匯。這里我們不贅述其底層原理,而是直接看 RocketMQ 在消息消費場景下,如何結合 Netty 實現零拷貝,將磁盤文件高效地發送到網絡。

圖片圖片

零拷貝的關鍵實現要點:

  • 當需要發送消息時,RocketMQ 首先通過內存映射從 commitlog 文件中獲取一個代表消息數據的 ByteBuf。重要的是,這個 ByteBuf 僅僅是一個引用,數據本身仍在頁緩存中,并未被加載到 Java 堆內存。
  • 然后,將這個 ByteBuf 包裝成一個 Netty 的 FileRegion 對象,并最終調用其 transferTo 方法。該方法的底層實現委托給了 FileChannel.transferTo()。

在 ManyMessageTransfer 類中可以看到具體的 transferTo 實現:

圖片圖片

FileChannel.transferTo() 在 Linux 系統上會觸發 sendfile() 系統調用。這個系統調用可以直接在內核空間中,將數據從文件句柄(頁緩存)拷貝到套接字緩沖區,避免了數據在內核態和用戶態之間的來回拷貝,實現了真正的零拷貝,極大地提升了數據傳輸效率。

本文從文件編程的視角,跟隨 RocketMQ 的設計學習了諸多優秀的工程技巧。希望這些內容能對你有所啟發

結語

學習 RocketMQ,我們學的不僅是 “術”(具體的實現技巧),更是 “道”(解決問題的思想和方法論)。希望通過本文的剖析,能為你打開一扇通往高性能存儲世界的大門,并在未來的系統設計中,能夠更加游刃有余地運用這些閃耀著智慧光芒的編程藝術。

責任編輯:武曉燕 來源: JAVA日知錄
相關推薦

2015-08-06 10:14:15

造輪子facebook

2020-09-08 08:45:39

jupyter插件代碼

2022-04-27 20:02:22

Dubbo注冊中心開發

2023-02-14 12:40:44

ChatGPTAI聊天

2023-02-06 17:27:48

2022-12-07 10:34:45

AST前端編譯

2018-09-03 14:05:08

編程語言Python編程技巧

2021-02-26 13:59:41

RocketMQProducer底層

2022-05-13 09:16:49

Python代碼

2021-10-09 18:26:59

二叉樹多叉樹搜索

2012-01-13 16:00:05

愛國者馮軍蘋果

2024-04-07 09:34:59

集群RemoteTransform

2020-06-11 18:06:03

電腦電路板元件

2021-10-28 19:10:51

RustPythonjs

2021-04-09 10:26:43

Python編程技術

2021-11-08 22:38:44

電腦科技C盤

2022-06-29 10:04:01

PiniaVuex

2024-05-14 08:11:56

ReactuseState造輪子

2021-03-15 09:44:39

Broker源碼RocketMQ

2023-02-23 19:39:06

華為汽車業務
點贊
收藏

51CTO技術棧公眾號

97碰碰视频| x99av成人免费| 成人观看免费完整观看| www.视频在线.com| 国产乱码精品一区二区三区忘忧草 | 成人欧美一区二区三区黑人麻豆| 亚洲综合在线小说| 五月婷婷视频在线| 亚洲一级毛片| 亚洲欧美日韩天堂| 成人欧美精品一区二区| 国产成+人+综合+亚洲欧美| 亚洲一区在线观看视频| 五月天亚洲综合小说网| 色欲av伊人久久大香线蕉影院| 日韩电影在线免费看| 欧美—级高清免费播放| 亚洲一区 欧美| 国产精品男女| 欧美一区二区三区免费视频| 国产成人无码av在线播放dvd| caoporn97在线视频| 国产欧美日韩在线观看| 国产一区免费| 亚洲国产精品成人久久蜜臀| 免费在线观看精品| 日韩美女视频免费看| 国产精久久久久久| 一区二区电影| 日韩在线精品视频| 99久久99久久精品免费看小说.| 国产成人福利av| 欧美一区二区三区在| 免费看黄色一级大片| 桃色av一区二区| 亚洲一区二区三区中文字幕| 特级西西444| 一区二区高清不卡| 欧美国产乱子伦| 欧美一区二区在线视频观看| 亚洲色偷精品一区二区三区| 大尺度一区二区| 国产精品露出视频| 丰满肉肉bbwwbbww| 丁香激情综合国产| 风间由美久久久| 乱色精品无码一区二区国产盗| 韩国理伦片一区二区三区在线播放| 国产精品免费一区| 亚洲无码久久久久| 九九视频精品免费| 91久久久久久国产精品| 99热在线只有精品| 国产成人av影院| 国产不卡一区二区三区在线观看| 亚洲第一天堂影院| 成人免费毛片嘿嘿连载视频| 国产精品二区三区| 三级视频在线看| 91女厕偷拍女厕偷拍高清| 精品国产乱码久久久久久108| 日本免费不卡视频| 91视视频在线直接观看在线看网页在线看| 国产综合18久久久久久| 亚洲欧美综合一区二区| 国产亚洲自拍一区| 一区二区三区|亚洲午夜| 精精国产xxxx视频在线| 一区二区三区日韩在线观看| www.在线观看av| 成人影院在线播放| 欧美午夜美女看片| 中文字幕国产免费| 日日夜夜精品视频| 亚洲成人黄色在线观看| 国产男男chinese网站| 国产精品亚洲二区| 日韩视频免费在线| 亚洲综合一二三| 三级欧美在线一区| 91精品免费视频| 亚洲精品一区二区三区四区| 久久久久久久综合色一本| 视频一区免费观看| 影音先锋中文在线视频| 精品国产精品三级精品av网址| 亚洲国产精品久久久久爰色欲| 国产a亚洲精品| 精品捆绑美女sm三区| 欧美日韩高清丝袜| 2023国产精品久久久精品双| 性欧美暴力猛交69hd| 中文字幕+乱码+中文字幕明步| 国产乱子伦视频一区二区三区| 精品久久久久久中文字幕动漫 | 久久久www免费人成精品| 亚洲欧洲日韩综合二区| 97人人在线视频| 欧美午夜精品久久久久久超碰| 欧美69精品久久久久久不卡| 国产日产精品_国产精品毛片| 伦理中文字幕亚洲| 久久久久久在线观看| 国产91在线|亚洲| 日韩亚洲欧美精品| www.51av欧美视频| 欧美电影一区二区三区| aaaaa一级片| 欧美破处大片在线视频| 国产精品免费看久久久香蕉| 姝姝窝人体www聚色窝| 中文字幕综合网| 爆乳熟妇一区二区三区霸乳| 丁香婷婷成人| 欧美成人性生活| 一本色道久久综合无码人妻| 久久久亚洲精品一区二区三区| 屁屁影院ccyy国产第一页| 国产成人a视频高清在线观看| 亚洲激情在线观看| 久久久久久久久艹| 狠狠色丁香久久婷婷综| 欧美亚洲免费在线| 碰碰在线视频| 亚洲成人国产精品| 亚洲综合网在线| 久久99久久精品欧美| 日韩电影天堂视频一区二区| 久久青草伊人| 亚洲国产精品国自产拍av秋霞| 精品国产精品国产精品| 国内精品不卡在线| 亚洲电影免费| 狂野欧美性猛交xxxx| 国产亚洲欧洲在线| 无码人妻精品一区二区蜜桃色欲| av亚洲精华国产精华| 久久手机在线视频| 91精品国产自产在线丝袜啪| 久久成人av网站| 国产精品久久综合青草亚洲AV| 国产精品乱码人人做人人爱| 一区二区三区网址| 久久麻豆精品| 成人网在线观看| 久久亚洲天堂| 日韩一区二区电影在线| 亚洲成人生活片| 国产成人综合在线播放| 男女啪啪免费观看| 成人免费在线电影网| 国内成人精品一区| 视频福利在线| 在线区一区二视频| 一二三四在线观看视频| 久久国产福利国产秒拍| 国产精品无码乱伦| 视频二区欧美毛片免费观看| 欧美日本啪啪无遮挡网站| www日本在线| 亚洲成年人影院| 少妇精品一区二区三区| 丝袜美腿亚洲综合| 一区二区三区四区欧美| 日韩精品一区二区三区中文 | 正在播放91九色| www.久久久.com| 欧美日本高清视频| 天堂91在线| 欧美日韩在线播| 欧美精品成人久久| 91看片淫黄大片一级| 成人精品视频一区二区| 亚洲成人国产| 国产一区免费视频| av在线日韩| 久久这里只有精品99| 嫩草影院一区二区| 欧美偷拍一区二区| 婷婷色中文字幕| ww亚洲ww在线观看国产| 中文字幕中文在线| 99精品免费| 亚洲成人av动漫| 超碰成人97| 国产精品免费福利| 24小时免费看片在线观看| 在线视频一区二区| 国产91免费看| 欧洲精品在线观看| 久久久99精品| 中国av一区二区三区| 美女黄色一级视频| 蜜臀久久99精品久久久久宅男| 亚洲欧美日韩国产yyy| 韩国女主播一区二区三区| 国产精品国产自产拍高清av水多| 日本在线观看高清完整版| 国产一区二区三区四区福利| 亚洲成a人片77777精品| 在线视频你懂得一区| 久久精品国产亚洲av高清色欲| 国产欧美一区二区三区网站| 日本人添下边视频免费| 精品一区二区三区视频| 亚洲午夜无码av毛片久久| 亚洲蜜桃视频| 日韩欧美一区二区在线观看| 成人在线超碰| 亚洲a级在线播放观看| 台湾佬成人网| 91国内在线视频| 91精品久久久| www.欧美精品| 黄色美女网站在线观看| 亚洲国产精品电影| 午夜精品久久久久久久爽| 欧美日韩成人激情| 亚洲天堂五月天| 色综合久久天天| 日本熟妇一区二区| 亚洲猫色日本管| 91传媒免费观看| 欧美韩国日本一区| 添女人荫蒂视频| 99久久99久久精品国产片果冻| 性生活在线视频| 国产乱子伦视频一区二区三区| 三上悠亚在线一区二区| 青青草91视频| 妞干网在线免费视频| 校园激情久久| www黄色日本| 国产欧美日韩一区二区三区在线| 韩国无码av片在线观看网站| 888久久久| 国产一二三四区在线观看| 久久久久久久久国产一区| 亚洲欧美丝袜| 欧美激情777| 在线免费一区| 真实国产乱子伦精品一区二区三区| 亚洲三区四区| 五月婷婷亚洲| 国产高清精品软男同| 亚洲精品国产偷自在线观看| 在线精品日韩| 国模大胆一区二区三区| 777久久精品一区二区三区无码| 一二三区不卡| avav在线播放| 国产视频一区三区| 不要播放器的av网站| 爽好久久久欧美精品| 亚洲不卡视频在线| 日韩电影免费一区| 亚洲美女性囗交| 国产成人精品www牛牛影视| 精品人妻人人做人人爽夜夜爽| 成人永久免费视频| 极品白嫩丰满美女无套| 亚洲国产精品99久久久久久久久| 国产亚洲精品精品精品| 亚洲视频一区在线| 国产真人真事毛片| 色综合久久天天| 一区二区三区在线免费观看视频| 777久久久精品| 午夜精品久久久久久久91蜜桃| 日韩第一页在线| 懂色一区二区三区| 欧美大成色www永久网站婷| av手机在线观看| 国产精品久久婷婷六月丁香| 一区二区三区| 精品国产一区二区三区四区vr| 精品国产一区二区三区久久久蜜臀| 一区二区在线观看网站| 激情自拍一区| 黄色三级视频片| 国产成人在线看| 人妻少妇一区二区| 亚洲视频 欧洲视频| 国产成人无码精品久久久久| 欧美系列日韩一区| 性欧美18一19性猛交| 亚洲人成免费电影| 羞羞视频在线免费国产| 日本国产高清不卡| 视频免费一区二区| 相泽南亚洲一区二区在线播放| 欧美区日韩区| 亚洲一级片网站| 97久久精品人人澡人人爽| 日韩一卡二卡在线观看| 午夜久久久久久| 91女人18毛片水多国产| 日韩成人中文字幕| 菠萝菠萝蜜在线视频免费观看| 青青青国产精品一区二区| 日本久久伊人| 视频一区视频二区视频三区高| 亚洲大胆在线| 亚洲精品www.| 久久精品亚洲国产奇米99 | 日韩欧美a级成人黄色| 国产精品一品二区三区的使用体验| 亚洲成人精品视频| 久久黄色美女电影| 国产精品久久久久久av下载红粉 | 熟女视频一区二区三区| 亚洲综合国产| 俄罗斯黄色录像| 综合久久国产九一剧情麻豆| 日韩黄色片网站| 日韩av影片在线观看| av免费在线观看网址| 国产精品丝袜视频| 亚洲丝袜美腿一区| 欧美日韩在线一| 成人午夜视频在线观看| 久久高清内射无套| 欧美日韩你懂的| 国产免费视频在线| 日韩av免费网站| 在线看成人短视频| jizzjizz国产精品喷水| 成人av免费在线| 欧美日韩中文视频| 日韩欧美中文字幕精品| 好吊日视频在线观看| 国产一区视频在线播放| 日韩精品免费| 日本在线一二三区| 亚洲欧洲精品一区二区三区不卡| 中文字幕永久在线| 中文字幕成人精品久久不卡| 日韩精品麻豆| 亚洲精品高清视频| 蜜乳av一区二区三区| www中文在线| 欧美精品日韩一区| 免费在线观看黄| 91九色单男在线观看| 亚洲最大av| 三上悠亚 电影| 亚洲一本大道在线| 污污网站免费在线观看| 17婷婷久久www| 国产成人调教视频在线观看| 亚洲人成色77777| 国产视频在线观看一区二区三区 | 日韩精品免费在线视频观看| 黑森林国产精品av| 久精品国产欧美| 亚洲欧美日韩一区在线观看| 瑟瑟视频在线观看| 欧美午夜片在线观看| 日本在线人成| 91精品天堂| 一区二区三区国产盗摄| aaaaa级少妇高潮大片免费看| 色婷婷亚洲婷婷| 中文字幕在线观看日本| 亚洲a中文字幕| 99热精品在线| 国产精品1区2区3区4区| 日韩午夜在线影院| 国内激情视频在线观看| 日本婷婷久久久久久久久一区二区| 蜜桃久久久久久| 欧美人妻一区二区| 亚洲美女福利视频网站| 亚洲老司机网| 日韩精品在线中文字幕| 久久久综合视频| 国产模特av私拍大尺度| 97在线观看视频国产| 国产探花一区| 红桃视频一区二区三区免费| 黄色一区二区在线观看| 国产精品免费观看| 99中文视频在线| 免费亚洲婷婷| www欧美com| 亚洲欧美国产va在线影院| 99久久999| 国产成人精品视频免费看| 亚洲欧洲精品一区二区三区不卡| 少妇人妻精品一区二区三区| 国产精品极品尤物在线观看| 欧美激情aⅴ一区二区三区| 大又大又粗又硬又爽少妇毛片| 欧美一卡2卡三卡4卡5免费| 亚洲成人看片| 日韩精品综合在线| 国产精品丝袜一区| 亚洲欧美日本在线观看| 亚洲最大激情中文字幕| 日本亚洲三级在线|