Kafka-common開源組件設計思路(附開源地址)

一、kafka-common組建說明

1.1 編寫背景

1.1.1 TA系統簡介

隨着大數據行業的發展,企業對於數據的利用越來越重視,對海量數據進行分析,按照數據分析的結果進行精細化運營也提上了各個企業的課題。

大數據時代的到來,企業越來越需要這一領域的專家,但大數據行業門檻高,自建平臺成本高,難度大,和其他部門配合效率低,很多情況下,效果也並不理想。

基於這一現象,數數科技基於hadoop,presto,kudu,kafka,flume等底層大數據組件,研發了一套企業級的海量數據即席分析系統——ThinkingAnalytics,簡稱TA系統。

該系統顛覆了以前開發人員根據數據分析人員提的需求進行定製化數據分析開發,然後將結果導出,交付給數據分析人員進行分析的傳統大數據分析模式。從根本上解決了各個傳統企業和互聯網企業的在海量數據分析上的痛點,能讓企業以極小的成本,將大數據真正在企業內部落地,爲企業的精細化運營做出極大的貢獻。

使用TA系統後,數據分析人員只需要簡單的設置和圖形拖拽,即可得到想要的數據分析結果,極大的減小了數據分析的人力成本,使得大數據分析的大規模應用得到可能。

1.1.2 kafka-common簡介

數據安全是企業首要關注的重點之一。

TA系統提供了私有云的部署(私有化)方式,使數據留在企業自己的服務器內,避免了企業數據的泄露。

但私有云的部署又涉及了很多問題,其中一個問題是,如何把技術棧做的足夠收斂,從而使得我們在持續集成,持續部署上儘可能的簡單。所以,我們大部分的核心組件都是自研。自己造輪子,可以在技術棧上保證足夠的統一和收斂。

所以,我們並沒有選擇一些開源的大數據流式處理引擎(例如spark,flink…),而最終自研了ta-data-etl流式處理引擎。

在ta-data-etl中,針對kafka consumer offset的管理,我們研發團隊開發了kafka-common組件,並將該組件開源,供給大家使用。

kafka-common組件是一款優秀的kafka consumer offset的管理組件,它已在各私有化客戶的實際生產中運行良久,經受住了實際的考驗,現特地將該組件的設計思路分享給大家。

1.1.3 系統地址及版本號

該組件地址

https://github.com/ThinkingDataAnalytics/kafka-common

當前版本0.2.0

歡迎大家使用。

1.1.4 選型背景

其實對於kafka consumer offset的管理,是有很多種方法可以選擇的,包括kafka自帶scala版本的high level和low lever的consumer,java版本的consumer,以及一些外部的例如spring-kafka組件等。

我們在TA系統V1.9之前也是使用kafka自帶的scala版本consumer(offset存在zookeeper裏),但在實際運行中,如果consumer的壓力過大,會造成zk的連接超時,並造成數據重複。並且因爲kafka的最新版本,對kafka的消息格式做了大規模的變更,也不再繼續維護scala版本consumer了,所以必須對這一塊的組件進行更新替換。

我們仔細分析了kafka consumer的api和開源社區上的幾個kafka consumer組件,發現還是我們自己手動管理offset比較方便,這樣更有利於我們對offset的管控。並且我們的元數據都是存在mysql中,將kafka consumer offset存在mysql中,並使用redis做爲備用存儲,可以保證元數據存儲的一致性。

二、設計要點

2.1 詳細說明

2.1.1 線程說明

主線程KafkaSubscribeConsumer

KafkaSubscribeConsumer主要是用來啓動consumer拉取線程的(生產環境中kafka consumer offset存在mysql中,並使用redis做爲備用存儲),它同時啓動了定時保存offset線程以及其它一些輔助線程

線程DaemonCloseThread 

該線程是接受停止信號的守護線程,會隨着系統的結束而自動停止

mysql及redis的定時保存offset線程MysqlOffsetPersist

MysqlOffsetPersist會啓動定時線程,定時保存緩存中的offset入mysql和redis

拉取線程KafkaSubscribeConsumeThread

KafkaSubscribeConsumeThread是核心線程,會根據processThreadNum參數啓動kafka consumer拉取線程,並將consumer註冊到RebalancerListener監聽器上,並啓動線程間的通訊信號offsetFlushBarrier(CyclicBarrier類)

KafkaSubscribeConsumeThread內有實際工作的working線程

2.1.2 類說明

MysqlOffsetPersist是讀取和寫入mysql/redis中kafka consumer offset的類,其具體邏輯在OffsetManager工具類中,其中,flush和persist是互斥的,一般在rebalance和stop時需要flush,平時只需定時的persist保存offset即可

KafkaConsumerRebalancerListener是在kafka consumer需要rebalance時進行的處理邏輯,也就是先save原先分配分區的offset,然後再重新讀取新分區的offset

KafkaSubscribeConsumeThread是拉取線程,其拉取數據後,會扔到processDataQueue這個隊列中

KafkaSubscribeConsumeThread.ProcessDataWorker是KafkaSubscribeConsumeThread的內部類,它是實際工作的working線程,將從processDataQueue隊列中讀取數據,並交給IdataLineProcessor這個消費接口進行消費

2.1.3 消費流程說明

kafka consumer從kafka中拿取數據,然後馬上暫停consumer,將數據放入隊列中,判斷隊列中的消息是否已經被消費完,如果unsent隊列爲空,則恢復consumer,否則,則讓consumer空跑,只進行最基本的心跳保持。

在消費結束時,用CyclicBarrier類在所有的處理完成後,將剩餘的offset刷入(flush)mysql/redis

2.1.4 外部需要實現的接口說明

IdataLineProcessor,實際的消費接口

StorePersist,備用存儲和異常處理接口(實際生產中備用存儲是redis)

TermMethod,如果需要外部信號進行安全退出,可使用該類

2.2 注意事項

1)  kafka consumer拿到數據,首先會放入processDataQueue隊列,如果該隊列滿了,則放入unsent隊列,並暫停consumer的消費,只保持最基本的心跳功能。

2)  整個consumer爲了保證性能,採用的是先提交offset,然後異步的進行消費,所以爲了確保exactly once,stop邏輯中會有很多標誌位,保證在安全退出時,隊列清空後,再進行關閉。

如果用kill -9之類的直接殺死進程,則blocking queue中的數據可能會丟失,需要特別注意。

後續,關閉策略可能會採取收到中斷信號時,將blockingqueue中的數據寫入本地的方案,增加系統的擼棒性和安全性。

3) 從unsent隊列放回processDataQueue隊列時,一定要注意如果放回失敗,則該消息是不應該從unsent隊列中刪除的,所以需要用的是offer()方法,只有成功後,纔會將該消息從隊列中刪除。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章