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

搞透Kafka的存儲架構,用起來直接起飛!

存儲 新聞
本文從 Kafka 存儲的場景剖析出發、kafka 存儲選型分析對比、再到 Kafka 存儲架構設計剖析,以及 Kafka 日志系統架構設計細節深度剖析,一步步帶你揭開了 Kafka 存儲架構的神秘面紗。

文章轉載自微信公眾號華仔聊技術 ,作者王江華,轉載本文請聯系華仔聊技術公眾號。

從這篇文章開始,我將對 Kafka 專項知識進行深度剖析, 今天我就來聊聊 kafka 的存儲系統架構設計, 說到存儲系統,大家可能對 MySQL 比較熟悉,也知道 MySQL 是基于 B+ tree 來作為它的索引數據結構。

Kafka 又是基于什么機制來存儲?為什么要設計成這樣?它解決了什么問題?又是如何解決的?里面又用到了哪些高大上的技術?

帶著這些疑問,我們就來和你聊一聊 Kafka 存儲架構設計背后的深度思考和實現原理。

認真讀完這篇文章,我相信你會對 Kafka 存儲架構,有更加深刻的理解,也能有思路來觸類旁通其他存儲系統的架構。

圖片

圖1 kafka 存儲架構大綱

一、kafka 存儲場景剖析

在講解 Kafka 的存儲方案之前,我們先來看看 Kafka 官網給的定義:

Apache Kafka is an open-source distributed event streaming platform used by thousands of companies for high-performance data pipelines, streaming analytics, data integration, and mission-critical applications.

翻譯成中文如下:

Apache kafka 是一個開源的分布式事件流處理平臺,由成千上萬的公司用于高性能的數據管道流分析、數據集成和關鍵任務的應用程序。

了解 Kafka 的老司機都知道它是從 Linkedin 內部孵化的項目,從一開始,Kafka 就是為了解決大數據的實時日志流而生的, 每天要處理的日志量級在千億規模。對于日志流的特點主要包括

  • 數據實時產生
  • 海量數據存儲與處理,所以它必然要面臨分布式系統遇到的高并發、高可用、高性能等三高挑戰

通過上面的背景可以得出:一切脫離業務場景談架構設計都是耍流氓

綜上我們看對于 Kafka 的存儲需求來說,要保證以下幾點:

1)存儲的主要是消息流(可以是簡單的文本格式也可以是其他格式,對于 Broker 存儲來說,它并不關心數據本身)

2)要支持海量數據的高效存儲、高持久化(保證重啟后數據不丟失)

3)要支持海量數據的高效檢索(消費的時候可以通過offset或者時間戳高效查詢并處理)

4)要保證數據的安全性和穩定性、故障轉移容錯性

二、kafka 存儲選型

有了上面的場景需求分析后, 我們接下來分析看看 Kafka 到底基于什么機制來存儲的,能否直接用現有我們了解到的關系型數據庫來實現呢?我們接著繼續深度分析。

1、存儲基本知識

我們先來了解下存儲的基本知識或者常識, 在我們的認知中,對于各個存儲介質的速度大體同下圖所示的,層級越高代表速度越快。很顯然,磁盤處于一個比較尷尬的位置,然而,事實上磁盤可以比我們預想的要快,也可能比我們預想的要慢,這完全取決于我們如何使用它。

圖片

圖2 各存儲介質對比分布(來自網絡)

關于磁盤和內存的 IO 速度,我們可以從下圖性能測試的結果看出普通機械磁盤的順序I/O性能指標是53.2M values/s,而內存的隨機I/O性能指標是36.7M values/s。由此似乎可以得出結論:磁盤的順序I/O性能要強于內存的隨機I/O性能。

圖片

圖3 磁盤和內存的 IO 速度對比(來自網絡)

另外從整個數據讀寫性能方面,有不同的實現方式,要么提高讀速度,要么提高寫速度。

1)提高讀速度:利用索引,來提高查詢速度,但是有了索引,大量寫操作都會維護索引,那么會降低寫入效率。常見的如關系型數據庫:mysql等

2)提高寫速度:這種一般是采用日志存儲, 通過順序追加寫的方式來提高寫入速度,因為沒有索引,無法快速查詢,最嚴重的只能一行行遍歷讀取。常見的如大數據相關領域的基本都基于此方式來實現。

2、Kafka 存儲方案剖析

上面從存儲基礎知識,以及存儲介質 IO 速度、讀寫性能方面剖析了存儲類系統的實現方式,那么我們來看看 Kafka 的存儲到底該采用哪種方式來實現呢?

對于 Kafka 來說, 它主要用來處理海量數據流,這個場景的特點主要包括:

1)寫操作:寫并發要求非常高,基本得達到百萬級 TPS,順序追加寫日志即可,無需考慮更新操作

2)讀操作:相對寫操作來說,比較簡單,只要能按照一定規則高效查詢即可(offset或者時間戳)

根據上面兩點分析,對于寫操作來說,直接采用順序追加寫日志的方式就可以滿足 Kafka 對于百萬TPS寫入效率要求。但是如何解決高效查詢這些日志呢?直接采用 MySQL 的 B+ tree 數據結構存儲是否可以?我們來逐一分析下:

如果采用 B+ tree 索引結構來進行存儲,那么每次寫都要維護索引,還需要有額外空間來存儲索引、更會出現關系型數據庫中經常出現的“數據頁分裂”等操作, 對于 Kafka 這種高并發的系統來說,這些設計都太重了,所以并不適合用。

但是在數據庫索引中,似乎有一種索引看起來非常適合此場景,即:哈希索引【底層基于Hash Table 實現】,為了提高讀速度, 我們只需要在內存中維護一個映射關系即可,每次根據 Offset 查詢消息的時候,從哈希表中得到偏移量,再去讀文件就可以快速定位到要讀的數據位置。但是哈希索引通常是需要常駐內存的,對于Kafka 每秒寫入幾百萬消息數據來說,是非常不現實的,很容易將內存撐爆, 造成 oom。

這時候我們可以設想把消息的 Offset 設計成一個有序的字段,這樣消息在日志文件中也就有序存放了,也不需要額外引入哈希表結構, 可以直接將消息劃分成若干個塊,對于每個塊,我們只需要索引當前塊的第一條消息的 Offset ,這個是不是有點二分查找算法的意思。即先根據 Offset 大小找到對應的塊, 然后再從塊中順序查找。如下圖所示:

圖片

圖4 kafka 稀疏索引查詢示意圖

這樣就可以快速定位到要查找的消息的位置了,在 Kafka 中,我們將這種索引結構叫做 “稀疏索引”。

三、kafka 存儲架構設計

上面從 Kafka 誕生背景、 存儲場景分析、存儲介質 IO 對比、以及 Kafka 存儲方案選型等幾個方面進行深度剖析, 得出了 Kafka 最終的存儲實現方案, 即基于順序追加寫日志 + 稀疏哈希索引

接下來我們來看看 Kafka 日志存儲結構:

圖片

圖5 kafka日志存儲結構

從上圖可以看出來,Kafka 是基于「主題 + 分區 + 副本 + 分段 + 索引」的結構:

1)kafka 中消息是以主題 Topic 為基本單位進行歸類的,這里的 Topic 是邏輯上的概念,實際上在磁盤存儲是根據分區 Partition 存儲的, 即每個 Topic 被分成多個 Partition,分區 Partition 的數量可以在主題 Topic 創建的時候進行指定。

2)Partition 分區主要是為了解決 Kafka 存儲的水平擴展問題而設計的, 如果一個 Topic 的所有消息都只存儲到一個 Kafka Broker上的話, 對于 Kafka 每秒寫入幾百萬消息的高并發系統來說,這個 Broker 肯定會出現瓶頸, 故障時候不好進行恢復,所以 Kafka 將 Topic 的消息劃分成多個 Partition, 然后均衡的分布到整個 Kafka Broker 集群中。

3)Partition 分區內每條消息都會被分配一個唯一的消息 id,即我們通常所說的 偏移量 Offset, 因此 kafka 只能保證每個分區內部有序性,并不能保證全局有序性。

4)然后每個 Partition 分區又被劃分成了多個 LogSegment,這是為了防止 Log 日志過大,Kafka 又引入了日志分段(LogSegment)的概念,將 Log 切分為多個 LogSegement,相當于一個巨型文件被平均分割為一些相對較小的文件,這樣也便于消息的查找、維護和清理。這樣在做歷史數據清理的時候,直接刪除舊的 LogSegement 文件就可以了。

5)Log 日志在物理上只是以文件夾的形式存儲,而每個 LogSegement 對應磁盤上的一個日志文件和兩個索引文件,以及可能的其他文件(比如以".snapshot"為后綴的快照索引文件等)。

四、kafka 日志系統架構設計

了解了 Kafka 存儲選型和存儲架構設計后, 我們接下來再深度剖析下 Kafka 日志系統的架構設計。

根據上面的存儲架構剖析,我們知道 kafka 消息是按主題 Topic 為基礎單位歸類的,各個 Topic 在邏輯上是獨立的,每個 Topic 又可以分為一個或者多個 Partition,每條消息在發送的時候會根據分區規則被追加到指定的分區中,如下圖所示:

圖片

圖6 4個分區的主題邏輯結構圖

1、日志目錄布局

那么 Kafka 消息寫入到磁盤的日志目錄布局是怎樣的?接觸過 Kafka 的老司機一般都知道 Log 對應了一個命名為<topic>-<partition>的文件夾。舉個例子,假設現在有一個名為“topic-order”的 Topic,該 Topic 中有4個 Partition,那么在實際物理存儲上表現為“topic-order-0”、“topic-order-1”、“topic-order-2”、“topic-order-3” 這4個文件夾。

看上圖我們知道首先向 Log 中寫入消息是順序寫入的。但是只有最后一個 LogSegement 才能執行寫入操作,之前的所有 LogSegement 都不能執行寫入操作。為了更好理解這個概念,我們將最后一個 LogSegement 稱為"activeSegement",即表示當前活躍的日志分段。隨著消息的不斷寫入,當 activeSegement 滿足一定的條件時,就需要創建新的 activeSegement,之后再追加的消息會寫入新的 activeSegement。

圖片

圖7 activeSegment示意圖

為了更高效的進行消息檢索,每個 LogSegment 中的日志文件(以“.log”為文件后綴)都有對應的幾個索引文件:偏移量索引文件(以“.index”為文件后綴)、時間戳索引文件(以“.timeindex”為文件后綴)、快照索引文件 (以“.snapshot”為文件后綴)。其中每個 LogSegment 都有一個 Offset 來作為基準偏移量(baseOffset),用來表示當前 LogSegment 中第一條消息的 Offset。偏移量是一個64位的 Long 長整型數,日志文件和這幾個索引文件都是根據基準偏移量(baseOffset)命名的,名稱固定為20位數字,沒有達到的位數前面用0填充。比如第一個 LogSegment 的基準偏移量為0,對應的日志文件為00000000000000000000.log。

我們來舉例說明,向主題topic-order中寫入一定量的消息,某一時刻topic-order-0目錄中的布局如下所示:

圖片

圖8 log 目錄布局示意圖

上面例子中 LogSegment 對應的基準位移是12768089,也說明了當前 LogSegment 中的第一條消息的偏移量為12768089,同時可以說明當前 LogSegment 中共有12768089條消息(偏移量從0至12768089的消息)。

注意每個 LogSegment 中不只包含“.log”、“.index”、“.timeindex”這幾種文件,還可能包含“.snapshot”、“.txnindex”、“leader-epoch-checkpoint”等文件,以及 “.deleted”、“.cleaned”、“.swap”等臨時文件。

另外,消費者消費的時候,會將提交的位移保存在 Kafka 內部的主題__consumer_offsets中。下面我們來看一個整體的日志目錄結構圖:

圖片

圖9 log 整體目錄布局示意圖

2、日志格式演變

對于一個成熟的消息中間件來說,日志格式不僅影響功能的擴展,還關乎性能維度的優化。所以隨著 Kafka 的迅猛發展,其日志格式也在不斷升級改進中,Kafka 的日志格式總共經歷了3個大版本:V0,V1和V2版本。

我們知道在 Kafka Partition 分區內部都是由每一條消息進行組成,如果日志格式設計得不夠精巧,那么其功能和性能都會大打折扣。

1)V0 版本

在 Kafka 0.10.0 之前的版本都是采用這個版本的日志格式的。在這個版本中,每條消息對應一個 Offset 和 message size。Offset 用來表示它在 Partition分區中的偏移量。message size 表示消息的大小。兩者合起來總共12B,被稱為日志頭部。日志頭部跟 Record 整體被看作為一條消息。如下圖所示:

圖片

圖10 V0 版本日志格式示意圖

  • crc32(4B):crc32校驗值。校驗范圍為magic至value之間。
  • magic(1B):日志格式版本號,此版本的magic值為0。
  • attributes(1B):消息的屬性。總共占1個字節,低3位表示壓縮類型:0 表示NONE、1表示GZIP、2表示SNAPPY、3表示LZ4(LZ4自Kafka 0.9.x 版本引入),其余位保留。
  • key length(4B):表示消息的key的長度。如果為-1,則沒有設置key。
  • key:可選,如果沒有key則無此字段。
  • value length(4B):實際消息體的長度。如果為-1,則消息為空。
  • value:消息體。

從上圖可以看出,V0 版本的消息最小為 14 字節,小于 14 字節的消息會被 Kafka 認為是非法消息。

下面我來舉個例子來計算一條消息的具體大小,消息的各個字段值依次如下:

  • CRC:對消息進行 CRC 計算后的值;
  • magic:0;
  • attribute:0x00(未使用壓縮);
  • key 長度:5;
  • key:hello;
  • value 長度:5;
  • value:world。

那么該條消息長度為:4 + 1 + 1 + 4 + 5 + 4 + 5 = 24 字節。

2)V1 版本

隨著 Kafka 版本的不斷迭代發展, 用戶發現 V0 版本的日志格式由于沒有保存時間信息導致 Kafka 無法根據消息的具體時間進行判斷,在進行清理日志的時候只能使用日志文件的修改時間導致可能會被誤刪。

從 V0.10.0 開始到 V0.11.0 版本之間所使用的日志格式版本為 V1,比 V0 版本多了一個 timestamp 字段,表示消息的時間戳。如下圖所示:

圖片

圖11 V1 版本日志格式示意圖

V1 版本比 V0 版本多一個 8B 的 timestamp 字段;

那么 timestamp 字段作用:

  • 對內:會影響日志保存、切分策略;
  • 對外:影響消息審計、端到端延遲等功能擴展

從上圖可以看出,V1 版本的消息最小為 22 字節,小于 22 字節的消息會被 Kafka 認為是非法消息。

總的來說比 V0 版本的消息大了 8 字節,如果還是按照 V0 版本示例那條消息計算,則在 V1 版本中它的總字節數為:24 + 8 = 32 字節。

3)V0、V1 版本的設計缺陷

通過上面我們分析畫出的 V0、V1 版本日志格式,我們會發現它們在設計上的一定的缺陷,比如:

  • 空間使用率低:無論 key 或 value 是否存在,都需要一個固定大小 4 字節去保存它們的長度信息,當消息足夠多時,會浪費非常多的存儲空間。
  • 消息長度沒有保存:需要實時計算得出每條消息的總大小,效率低下。
  • 只保存最新消息位移。
  • 冗余的 CRC 校驗:即使是批次發送消息,每條消息也需要單獨保存 CRC。

4)V2 版本

針對 上面我們分析的 關于 V0、V1 版本日志格式的缺陷,Kafka 在 0.11.0.0 版本對日志格式進行了大幅度重構,使用可變長度類型解決了空間使用率低的問題,增加了消息總長度字段,使用增量的形式保存時間戳和位移,并且把一些字段統一抽取到 RecordBatch 中。

圖片

圖12 V2 版本日志格式示意圖

從以上圖可以看出,V2 版本的消息批次(RecordBatch),相比 V0、V1 版本主要有以下變動:

  • 將 CRC 值從消息中移除,被抽取到消息批次中。
  • 增加了 procuder id、producer epoch、序列號等信息主要是為了支持冪等性以及事務消息的。
  • 使用增量形式來保存時間戳和位移。
  • 消息批次最小為 61 字節,比 V0、V1 版本要大很多,但是在批量消息發送場景下,會提供發送效率,降低使用空間。

綜上可以看出 V2 版本日志格式主要是通過可變長度提高了消息格式的空間使用率,并將某些字段抽取到消息批次(RecordBatch)中,同時消息批次可以存放多條消息,從而在批量發送消息時,可以大幅度地節省了磁盤空間。

3、日志清理機制

Kafka 將消息存儲到磁盤中,隨著寫入數據不斷增加,磁盤占用空間越來越大,為了控制占用空間就需要對消息做一定的清理操作。從上面 Kafka 存儲日志結構分析中每一個分區副本(Replica)都對應一個 Log,而 Log 又可以分為多個日志分段(LogSegment),這樣就便于 Kafka 對日志的清理操作。

Kafka提供了兩種日志清理策略:

  • 日志刪除(Log Retention)

按照一定的保留策略直接刪除不符合條件的日志分段(LogSegment)。

  • 日志壓縮(Log Compaction)

針對每個消息的key進行整合,對于有相同key的不同value值,只保留最后一個版本。

這里我們可以通過 Kafka Broker 端參數 log.cleanup.policy 來設置日志清理策略,默認值為 “delete”,即采用日志刪除的清理策略。如果要采用日志壓縮的清理策略,就需要將 log.cleanup.policy 設置為 “compact”,這樣還不夠,必須還要將log.cleaner.enable(默認值為 true)設為 true。

如果想要同時支持兩種清理策略, 可以直接將 log.cleanup.policy 參數設置為“delete,compact”。

1)日志刪除

Kafka 的日志管理器(LogManager)中有一個專門的日志清理任務通過周期性檢測和刪除不符合條件的日志分段文件(LogSegment),這里我們可以通過 Kafka Broker 端的參數 log.retention.check.interval.ms 來配置,默認值為300000,即5分鐘。

在 Kafka 中一共有3種保留策略:

①基于時間策略

日志刪除任務會周期檢查當前日志文件中是否有保留時間超過設定的閾值(retentionMs) 來尋找可刪除的日志段文件集合(deletableSegments)。

其中retentionMs可以通過 Kafka Broker 端的這幾個參數的大小判斷的

log.retention.ms > log.retention.minutes > log.retention.hours優先級來設置,默認情況只會配置 log.retention.hours 參數,值為168即為7天。

這里需要注意:刪除過期的日志段文件,并不是簡單的根據該日志段文件的修改時間計算的,而是要根據該日志段中最大的時間戳 largestTimeStamp 來計算的,首先要查詢該日志分段所對應的時間戳索引文件,查找該時間戳索引文件的最后一條索引數據,如果時間戳值大于0,則取值,否則才會使用最近修改時間(lastModifiedTime)。

【刪除步驟】:

  • 首先從 Log 對象所維護的日志段的跳躍表中移除要刪除的日志段,用來確保已經沒有線程來讀取這些日志段。
  • 將日志段所對應的所有文件,包括索引文件都添加上“.deleted”的后綴。
  • 最后交給一個以“delete-file”命名的延遲任務來刪除這些以“ .deleted ”為后綴的文件。默認1分鐘執行一次, 可以通過 file.delete.delay.ms 來配置。

圖片

圖13 基于時間保留策略示意圖

②基于日志大小策略

日志刪除任務會周期檢查當前日志大小是否超過設定的閾值(retentionSize) 來尋找可刪除的日志段文件集合(deletableSegments)。

其中 retentionSize 這里我們可以通過 Kafka Broker 端的參數log.retention.bytes來設置, 默認值為-1,即無窮大。

這里需要注意的是 log.retention.bytes 設置的是Log中所有日志文件的大小,而不是單個日志段的大小。單個日志段可以通過參數 log.segment.bytes 來設置,默認大小為1G。

【刪除步驟】:

  • 首先計算日志文件的總大小Size和retentionSize的差值,即需要刪除的日志總大小
  • 然后從日志文件中的第一個日志段開始進行查找可刪除的日志段的文件集合(deletableSegments)
  • 找到后就可以進行刪除操作了

圖片

圖14 基于日志大小保留策略示意圖

③基于日志起始偏移量

該策略判斷依據是日志段的下一個日志段的起始偏移量 baseOffset 是否小于等于 logStartOffset,如果是,則可以刪除此日志分段。

【如下圖所示 刪除步驟】:

  • 首先從頭開始遍歷每個日志段,日志段 1 的下一個日志分段的起始偏移量為20,小于logStartOffset的大小,將日志段1加入deletableSegments。
  • 日志段2的下一個日志偏移量的起始偏移量為35,也小于logStartOffset的大小,將日志分段2頁加入deletableSegments。
  • 日志段3的下一個日志偏移量的起始偏移量為50,也小于logStartOffset的大小,將日志分段3頁加入deletableSegments。
  • 日志段4的下一個日志偏移量通過對比后,在logStartOffset的右側,那么從日志段4開始的所有日志段都不會加入deletableSegments。
  • 待收集完所有的可刪除的日志集合后就可以直接刪除了。

圖片

圖15 基于日志起始偏移量保留策略示意圖

2)日志壓縮

日志壓縮 Log Compaction 對于有相同key的不同value值,只保留最后一個版本。如果應用只關心 key 對應的最新 value 值,則可以開啟 Kafka 相應的日志清理功能,Kafka會定期將相同 key 的消息進行合并,只保留最新的 value 值。

Log Compaction 可以類比 Redis 中的 RDB 的持久化模式。我們可以想象下,如果每次消息變更都存 Kafka,在某一時刻, Kafka 異常崩潰后,如果想快速恢復,可以直接使用日志壓縮策略, 這樣在恢復的時候只需要恢復最新的數據即可,這樣可以加快恢復速度。

圖片

圖16 日志壓縮策略示意圖

4、磁盤數據存儲

們知道 Kafka 是依賴文件系統來存儲和緩存消息,以及典型的順序追加寫日志操作,另外它使用操作系統的 PageCache 來減少對磁盤 I/O 操作,即將磁盤的數據緩存到內存中,把對磁盤的訪問轉變為對內存的訪問。

在 Kafka 中,大量使用了 PageCache, 這也是 Kafka 能實現高吞吐的重要因素之一, 當一個進程準備讀取磁盤上的文件內容時,操作系統會先查看待讀取的數據頁是否在 PageCache 中,如果命中則直接返回數據,從而避免了對磁盤的 I/O 操作;如果沒有命中,操作系統則會向磁盤發起讀取請求并將讀取的數據頁存入 PageCache 中,之后再將數據返回給進程。同樣,如果一個進程需要將數據寫入磁盤,那么操作系統也會檢查數據頁是否在頁緩存中,如果不存在,則 PageCache 中添加相應的數據頁,最后將數據寫入對應的數據頁。被修改過后的數據頁也就變成了臟頁,操作系統會在合適的時間把臟頁中的數據寫入磁盤,以保持數據的一致性。

除了消息順序追加寫日志、PageCache以外, kafka 還使用了零拷貝(Zero-Copy)技術來進一步提升系統性能, 如下圖所示:

圖片

圖17 kafka 零拷貝示意圖

這里也可以查看之前寫的 Kafka 三高架構設計剖析 中高性能部分。

消息從生產到寫入磁盤的整體過程如下圖所示:

圖片

圖18 日志消息寫入磁盤過程示意圖

五、總結

本文從 Kafka 存儲的場景剖析出發、kafka 存儲選型分析對比、再到 Kafka 存儲架構設計剖析,以及 Kafka 日志系統架構設計細節深度剖析,一步步帶你揭開了 Kafka 存儲架構的神秘面紗。

責任編輯:張燕妮 來源: 華仔聊技術
相關推薦

2022-04-01 10:08:21

SQL 優化MySQL數據庫

2025-11-20 02:25:00

Vs CodeClaudeCursor

2023-12-28 10:01:05

ChatGPT技巧信息

2024-01-10 09:18:58

RustAIGPT

2021-06-30 09:20:18

NuShell工具Linux

2025-09-08 04:07:00

SpringApache工具

2023-02-07 06:55:26

Kafka消費消息

2021-03-10 09:54:43

RustNuShell系統

2024-05-21 10:28:51

API設計架構

2024-07-04 11:33:33

2025-11-10 09:04:55

2022-05-22 21:16:46

TypeScriptOmit 工具

2012-07-11 09:34:39

微軟云計算

2021-07-06 06:39:58

Kafka消息隊列系統

2020-07-06 15:13:16

安卓AirDrop無線傳輸

2020-01-06 15:00:43

Linux電腦發行版

2021-09-18 08:52:45

人工智能

2015-05-28 10:35:07

前端gulpdemo

2022-09-20 07:46:15

重試組件retrying

2016-03-17 09:45:17

react雙向綁定插件
點贊
收藏

51CTO技術棧公眾號

亚洲经典一区二区三区| 免费在线观看av网址| 日韩毛片一区| 亚洲啪啪综合av一区二区三区| 51国偷自产一区二区三区的来源 | 成人春色在线观看免费网站| 欧美日韩一区二区三区| 一区二区成人国产精品| 国内老熟妇对白xxxxhd| 久久九九免费| 九九九久久国产免费| 日本少妇高潮喷水xxxxxxx| 成人51免费| 在线这里只有精品| 992tv快乐视频| 成人福利在线| 99麻豆久久久国产精品免费 | av男人一区| 欧美日韩一卡二卡| 欧美 日韩 国产一区| 在线xxxx| 国产精品福利一区二区三区| 欧美成人综合一区| www.com欧美| 麻豆视频观看网址久久| …久久精品99久久香蕉国产| 99视频只有精品| 日韩免费看片| 国产亚洲精品日韩| 久久精品国产亚洲av麻豆| 日韩中文字幕无砖| 欧美精品日韩精品| 国产91色在线观看| 网友自拍亚洲| 欧美性xxxx极品hd满灌| 国产精品久久..4399| 97caopron在线视频| 国产精品国模大尺度视频| 日韩电影免费观看在| 日本人妖在线| 2欧美一区二区三区在线观看视频| 成人18视频| 国产jzjzjz丝袜老师水多| 毛片不卡一区二区| 国产欧美精品一区二区| 在线观看你懂的网站| 男女精品视频| 欧洲成人免费视频| 国产剧情在线视频| 国产乱码精品| 欧美最顶级丰满的aⅴ艳星| 国产成人综合欧美精品久久| 欧美日韩网站| 久久久久久久国产| 国产极品美女高潮无套嗷嗷叫酒店| 一区二区电影在线观看| 操91在线视频| 中文字幕手机在线观看| 欧美日韩1区| 国内成人精品一区| 久草视频在线观| 免费日韩av| 国产精品老女人视频| 怡红院成永久免费人全部视频| 青娱乐精品视频| 成人美女av在线直播| 99热这里只有精品在线| 国产不卡视频在线播放| 国内精品久久国产| 男人久久精品| 国产精品毛片大码女人| 免费国产成人看片在线| 欧美一卡二卡| 欧美性开放视频| 天天综合网日韩| 国产亚洲高清一区| 亚洲福利在线看| 一区二区黄色片| 97精品视频| 欧美国产日韩一区| 亚洲 欧美 成人| 麻豆一区二区三| 国产麻豆一区二区三区在线观看| 亚洲色欧美另类| 国产精品久久看| 欧美视频在线第一页| 天堂8中文在线最新版在线| 欧美性感一区二区三区| 亚洲丝袜在线观看| 亚洲国产精品嫩草影院久久av| 中文字幕日韩免费视频| 免费网站看av| 日韩国产在线观看一区| 114国产精品久久免费观看| 婷婷综合激情网| 国产精品国产a| 日韩精品―中文字幕| 欧美日韩va| 欧美一区二区精品久久911| 泷泽萝拉在线播放| 综合久久99| 国产精品户外野外| 人妻一区二区三区| 18涩涩午夜精品.www| 精品99在线视频| 精品一区二区三区中文字幕在线| 国产偷亚洲偷欧美偷精品| 午夜爱爱毛片xxxx视频免费看| 国产一区二区三区久久久久久久久| 成人黄色在线免费| 久青草国产在线| 亚洲成人动漫一区| 日本美女久久久| 青草国产精品| 欧美最近摘花xxxx摘花| 丰满肉肉bbwwbbww| 中文字幕亚洲精品在线观看| 免费成人在线视频网站| 欧美成年网站| 久久黄色av网站| 中文字幕在线天堂| 26uuu精品一区二区| 青青在线视频免费观看| 99久久er| 国产亚洲日本欧美韩国| 欧美一区二区三区四| 国产99久久久国产精品潘金| 中文字幕精品—区二区日日骚| 波多野结衣久久精品| 亚洲福利影片在线| 日本少妇bbwbbw精品| 国产精品资源在线看| 伊甸园精品99久久久久久| 欧美男体视频| 亚洲日本成人女熟在线观看| 中文字幕一区二区三区精品| 国产iv一区二区三区| 波多野结衣 作品| 国产精品亚洲欧美日韩一区在线| 中文字幕精品在线视频| 日本欧美www| 欧美极品美女视频| 黑森林精品导航| 成久久久网站| 国产精品丝袜白浆摸在线| av一本在线| 欧美色成人综合| 美国美女黄色片| 蜜桃视频一区二区| 正在播放国产精品| 高清国产一区二区三区四区五区| 精品国产拍在线观看| 国产精品国产精品国产专区| 亚洲欧美综合网| 91蝌蚪视频在线| 欧美激情第10页| 国产激情美女久久久久久吹潮| 国产丝袜在线播放| 日韩www在线| 香蕉污视频在线观看| 国产女人18水真多18精品一级做 | 国产精品综合久久| 7777精品伊人久久久大香线蕉完整版| 免费黄频在线观看| 欧美va天堂在线| 国产一级精品aaaaa看| 欧美调教sm| 一个色综合导航| 一区二区美女视频| 一区二区三区**美女毛片| 黄色av电影网站| 美女精品网站| 国产日韩视频在线播放| www.神马久久| 国产成一区二区| av网站在线免费| 亚洲精品狠狠操| 中日精品一色哟哟| 亚洲综合无码一区二区| 三上悠亚ssⅰn939无码播放| 免费久久精品视频| 日韩精品在线观看av| 自拍偷拍一区| 91香蕉嫩草影院入口| 精精国产xxxx视频在线野外| 正在播放欧美视频| 高潮一区二区三区乱码| 91精品福利在线| 久久久久黄色片| 国产婷婷色一区二区三区四区| 亚洲综合激情视频| 国产精品嫩草99av在线| 国产精品99久久久久久大便| 欧美男人操女人视频| 国产美女精品视频免费观看| 白白色在线观看| 中国人与牲禽动交精品| 女人18毛片水真多18精品| 欧美性视频一区二区三区| 久久久久久久久99| 中文字幕免费不卡| 在线免费播放av| 国产一区二区伦理片| 亚洲色精品三区二区一区| 女主播福利一区| 神马欧美一区二区| 欧美wwwsss9999| 92看片淫黄大片欧美看国产片| free欧美| 91精品国产91久久久| 成人在线播放| 最新91在线视频| 美女欧美视频在线观看免费| 精品久久久久一区| 国产精品女人久久久| 91精品福利视频| 在线天堂中文字幕| 亚洲成av人片www| 久久久久久久久久网站| 国产精品久久三区| 欧美三级视频网站| 91丨九色丨蝌蚪丨老版| 影音先锋资源av| 国产精品一区二区免费不卡| 国产一伦一伦一伦| 日韩电影一区二区三区四区| 久久成人免费观看| 雨宫琴音一区二区在线| 日韩人妻一区二区三区蜜桃视频| 久久理论电影| 一本久久a久久精品vr综合| jiujiure精品视频播放| 欧美极品视频一区二区三区| 精品淫伦v久久水蜜桃| 肥熟一91porny丨九色丨| 国产一区二区高清在线| 91香蕉国产在线观看| 国产一区2区在线观看| 91系列在线播放| 日韩精品一区二区三区中文 | 久久九九国产精品| 女人被狂躁c到高潮| 91日韩精品一区| 麻豆国产精品一区| 26uuu久久天堂性欧美| 疯狂揉花蒂控制高潮h| 91麻豆精品秘密| 免费看污片网站| 国产精品区一区二区三| a级黄色免费视频| 国产精品乱人伦| 国产大片免费看| 亚洲小说欧美激情另类| 日韩av女优在线观看| 欧美日韩国产精品一区二区三区四区 | 日本a√在线观看| 日本中文在线一区| 女人高潮一级片| 国产成人a级片| 在线看黄色的网站| 久久蜜桃一区二区| 三区四区在线观看| 亚洲色图视频免费播放| 欧美日韩国产精品综合 | 视频在线观看一区二区| 国产精品久久麻豆| 欧美精品videossex性护士| 黄色在线观看www| 国产精品久久久999| 国产高清亚洲| 好看的日韩精品| 精品大片一区二区| 精品一区二区成人免费视频| 雨宫琴音一区二区在线| 国产精彩免费视频| 国产精品综合视频| 在线免费观看日韩av| **性色生活片久久毛片| 久久久久久久久久久久久久免费看 | 国产一区二区三区高清在线观看| 黄色大片在线播放| 91高清视频在线免费观看| aaaa欧美| 国产美女精品在线观看| 欧美日韩一区二区三区视频播放| 热这里只有精品| 久久精品免费| 能看毛片的网站| 久久精品视频一区二区| 日韩精品123区| 欧美日韩一二三四五区| 国产精品九九九九| 日韩电影视频免费| 精品欧美色视频网站在线观看| 久久人人爽人人爽人人片av高清| 日韩不卡在线| 国产精品综合久久久久久| 热久久天天拍国产| 97成人在线免费视频| 国产自产v一区二区三区c| 中国黄色a级片| 一区二区国产盗摄色噜噜| aaa在线视频| 亚洲国产欧美精品| 91高清在线观看视频| 国产精品久久久久久久久久久新郎 | 亚洲国产精品视频一区| 在线日本成人| av在线网站免费观看| 亚洲国产成人一区二区三区| 欧美亚洲天堂网| 日韩一区二区三| 欧美午夜电影一区二区三区| 欧美一级在线亚洲天堂| 超碰精品在线观看| 免费看污污视频| 久久99精品久久久久久久久久久久| 国内精品久久99人妻无码| 亚洲一区二区三区爽爽爽爽爽| 91麻豆一区二区| 最新日韩中文字幕| 成人涩涩视频| 欧美中日韩一区二区三区| 99国产精品| 久久精品aⅴ无码中文字字幕重口| 国产精品传媒视频| 五月婷婷激情五月| 亚洲男人天堂手机在线| 久久久男人天堂| 国产精品国产精品国产专区不卡| 我不卡伦不卡影院| www.污污视频| 亚洲欧洲成人av每日更新| 在线观看免费黄色小视频| 一区二区在线视频播放| 欧洲一级精品| 欧美日韩精品久久| 乱码第一页成人| 成都免费高清电影| 色视频欧美一区二区三区| 精华区一区二区三区| 国产精品电影一区| 欧美亚洲在线日韩| 国产精品拍拍拍| 国产精品久久久爽爽爽麻豆色哟哟| 97人妻一区二区精品视频| 亚洲日韩中文字幕在线播放| 日本免费久久| 日韩女优中文字幕| 免费一级欧美片在线观看| 亚洲午夜精品久久久久久高潮 | www.精品在线| 日韩美女久久久| 性一交一乱一色一视频麻豆| 欧美激情三级免费| 日韩高清一级| 国产精品69页| 亚洲日本电影在线| 亚洲欧美激情在线观看| 91a在线视频| 欧美色图一区| 四虎国产精品永久免费观看视频| 亚洲一区在线观看免费观看电影高清| 亚洲av无码乱码在线观看性色| 久久久久亚洲精品国产 | 性欧美18一19内谢| 国产ts人妖一区二区| 免费在线不卡视频| 国产一区二区三区丝袜| 成人国产精品一区二区网站| 搞av.com| 久久久国产一区二区三区四区小说| 探花国产精品一区二区| 久久五月天色综合| 免费福利视频一区| 特级丰满少妇一级| 亚洲综合一区二区三区| 免费黄网站在线观看| 成人综合国产精品| 夜夜嗨一区二区| 91n在线视频| 亚洲国产精品福利| 成人福利片在线| 久久精品xxx| 国产欧美一区二区精品秋霞影院 | 26uuu亚洲综合色| 亚洲专区在线播放| 91国产精品电影| 国产精品成久久久久| 亚洲色图14p| 91精品国产一区二区三区| xxx欧美xxx| 亚洲色成人www永久在线观看| 国产午夜精品一区二区三区嫩草 | 久久久另类综合| 国产成人精品白浆久久69| 国产va免费精品高清在线观看| 自拍偷拍欧美| 日本美女xxx| 亚洲精品99久久久久中文字幕|