kafka的概念理解

最近剛接觸到kafka,所有做一些理解總結:如有建議和意見歡迎留言討論

  • 消息隊列的前世今生:

消息協議?

JMS協議 提供的 2 種消息模型 ,5 種不同的消息正文格式: 本質是java接口api
AMQP協議 提供了 5 種消息模型 ,1 種不同的消息正文格式byte[](二進制) ,兼容 JMS,跨語言,跨平臺
兩種協議的區別: AMQP爲消息定義了線路層(wire-level protocol)的協議,而JMS所定義的是API規範

消息模型?

發佈-訂閱模式(自由增加刪除訂閱),還有點對點訂閱模式(一個消息只有一個消費者)
提供了五種消息模型:①direct exchange;②fanout exchange;③topic change;④headers exchange;⑤system exchange。本質來講,後四種和JMS的pub/sub模型沒有太大差別,僅是在路由機制上做了更詳細的劃分; 由Exchange 提供的路由算法,AMQP可以提供多樣化的路由方式來傳遞

消息類型?
JMS 五種不同的消息正文格式:
StreamMessage – Java原始值的數據流
MapMessage–一套名稱-值對
TextMessage–一個字符串對象
ObjectMessage–一個序列化的 Java對象
BytesMessage–一個字節的數據流
AMQP只有一種:byte[](二進制)

scala應用,運行需要scala編譯環境,client代碼由JAVA重寫過

概念:
生產者

  • 代理(server,broker)
  • 消費者
  • 主題(topic)
  • 分區()
  • 消費組()

此處應該有圖(待補充)

代理:即爲kafka服務端,多個broker實現kafka集羣(這裏是指水平擴展,如果用到zookeeper則主要用來存儲集羣的元數據信息(以前還會用來存儲offset,現在的一般做法是存儲在另一個topic中)而不用關心一致性[zookeeper集羣間需要關注一致性] )
主題:一組消息的抽象(如消費者的訂單信息抽象爲個人消費主題)
消費者:需要指定消費組,默認在test-consumer-group中;每個消費者需要指定全局唯一id(client.id),默認有生成規則;
消費組:是用來實現對一個主題的消息進行多播或者單播的手段

這裏主要詳述之間的關係,基本定義不再複述:

  1. consumer group是kafka提供的可擴展的消費者機制。
    (理解:可以通過增加group實現消息多播[消息多次消費],也具有容錯性(避免重複消費[只需要將消費者定義在一個group內即可]))
  2. 既然是一個組,那麼組內必然可以有多個消費者或消費者實例(consumer instance),它們共享一個公共的ID,即group
    ID。
  3. 組內的所有消費者協調在一起來消費訂閱主題。
    (需要協調的具體場景,如發生消費者增減,分區增減時的reblance[偏移量offset];組內協調分區)。

分區和消費者的對應關係(這裏前提是一個topic和一個group)

當然,每個分區只能由同一個消費組內的一個consumer來消費。個人認爲,理解consumer group記住下面這三個特性就好了:

consumer group下可以有一個或多個consumer instance,consumer instance可以是一個進程,也可以是一個線程
group.id 是一個字符串,唯一標識一個consumer group
consumer group下訂閱的topic下的每個分區只能分配給某個group下的一個consumer(設計用來避免重複消費)(當然該分區還可以被分配給其他group,由其他組中的消費者消費)

分區:理解成避免消息重複消費的一種機制

通過生產者獲取broker上該主題的分區信息:
partitions = producer.partitionsFor(topic);
[
Partition(topic = topic_msg111, partition = 2, leader = 243, replicas = [243,], isr = [243,],
Partition(topic = topic_msg111, partition = 1, leader = 281, replicas = [281,], isr = [281,], Partition(topic = topic_msg111, partition = 0, leader = 279, replicas = [279,], isr = [279,] ]
isr:副本列表,保存的是broker.id(節點id)

分區是邏輯上的名詞,對應到物理機上爲文件系統的一個個log文件
分區的作用:(消費不同分區消息的)併發,(分區內消費)有序,(分區副本實現)高可用,(消息寫入分區)效率高,消息持久化
①消費者和分區之間的關係抽象爲n:n(實際使用多是1:1)
②基於偏移量讀取消息,但是偏移量本身沒有額外的索引,所以消息只能按序
③基於多副本的高可用策略,需要zookeeper等實現選舉算法等策略來保證一致性和故障轉移
④分區內寫入消息的方式是有序的(追加寫入log,每條消息對應一個偏移量[理解成文件中某條消息的定位])使寫入速度較快
⑤消息持久化策略:基於時間跨度,基於分區大小

kafka出現重複消費的問題原因及解決思路?
位移(偏移量)提交有兩種方式:自動或手動 ,採用手動提交有兩種處理方式:
實際使用:
1)在消息pull下來後業務處理前立即提交,
2)在消息pull下來後業務處理完成再提交
重複消費的原因:
第1)種可能出現offset提交成功,但消息處理異常了,導致消息丟失,
第2)種可能出現因爲業務處理時間過長,超過session.out.time,導致消費者假死,kafka觸發rebalance,從而提交offset失敗,當再次觸發業務時會出現重複消費
思路:
通常的做法是確保消息處理成功之後提交位移。但如果消息處理時間過長導致rebalance確實會出現重複消費——目前Kafka無法完美地避免該問題的出現。可以調整max.poll.interval.ms來避免這種情況的出現~

近期Kafka會推出支持事務的消費處理,那時才能實現“精確一次”的消費語義。

出現poll阻塞 ?
實際使用:連接server的ip和port未能連接到broker,會在生成協調器時陷入死循環,目前官方尚未修復
原因:Block until the coordinator for this group is known
AbstractCoordinator.ensureCoordinatorKnown()

如何確定分區數呢?
https://www.cnblogs.com/huxi2b/p/4757098.html
不同分區消費實現有序性的可能?

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