Kafka Indexing Service開發的目的是爲了增強Kafka中數據的實時攝入。其特性如下:
- 保障數據攝入的Exactly Once。
- 可以攝入任意時間戳的數據,而不僅僅是當前數據。
- 可以根據Kafka分區的變化二調整任務的數量。
影響數據攝入Exactly Once的主要因素是Kafka的Offset管理。Kafka Indexing Service爲了實現Exactly Once語義,去掉了windowPeriod,並採用底層API實現了對Offset的事務管理。
Kafka Indexing Service的類圖如下:
其中:
KafkaSupervisor
負責整個Kafka Indexing Service的創建以及其整個生命週期的管理,它監管Kafka Indexing Service的狀態來完成協調移交,管理失敗,同時保障添加/刪除Kafka 分區以後的可擴展性以及任務的多副本執行。
TaskGroups
是KafkaSupervisor管理partition,Offset和Indexing service的數據結構,用來保障任務的多副本執行。每個TaskGroups中的所有任務做的都是相同的事情。讀取分配給TaskGroups的所有partition的數據,而且都是從相同的Offset開始讀取。通過修改replicas的值來調整任務副本數量。
KafkaIndexTask
從KafkaIOConfig的startPosition中的offset處開始讀取數據,一直到endPartition的結束Offset處結束讀取,發佈移交segment。在執行過程中,startPosition中的Offset不會變,endPosition的Offset初始設置爲: Long.MAX_VALUE。KafkaSupervisor通過修改endPosition的值來結束任務的執行。運行中的任務有兩種狀態:讀取和發佈。任務會保持讀取狀態,直到達到taskDuration以後進入發佈狀態。接下來會保持發佈狀態,直到生成segment,並推送至Deep Storage,然後His節點加載。或者達到completionTimeout的時間。
Appenderator
用來索引數據,採用LSM-Tree結構。這個模塊負責索引和查詢數據,並將Segment推送到Deep Storage中,他只將Segment信息發佈到元數據存儲中。
FiniteAppendratorDriver
驅動Appendrator完成有限流式數據的索引,在索引結束後執行移交操作。它完成Appenderator不能做的那些事情,包括SegmentAllocator將數據分配到指定的Segment,監控移交等。
Kafka Indexing Service利用Kafka的底層Consumer接口,從傳入startOffsets Map{partition, startOffset} 處讀取數據,使用FiniteAppendratorDriver構建Segment。FiniteAppendratorDriver採用有限流失數據的處理方式,讀取固定時間段的數據。
FiniteAppendratorDriver會帶來副作用,會產生一些碎片化的Segment,特別是日誌跨時段亂序延遲嚴重的情況。
如何使用?
將該Extension添加到Overlord和MiddleManager中:
druid.extensions.loadList=["other-modules", "kafka-indexing-service"]
通過 http://<OVERLORD_IP>:<OVERLORD_PORT>/druid/indexer/v1/supervisor 來提交任務。