kafka集群

Kafka的設計都是為了實現kafak消息隊列消費數據的語義
Kafka消息隊列中數據消費的三種語義:
- at-most-once:至多一次
會出現數據丟失的問題 - at-least-once:至少一次
會出現數據重復的問題 - exactly-once:有且僅有一次
只消費處理成功一次
所有消息隊列的目標
kakfa卡只能保證局部有序,如何實現全局有序

kafka中每個分區(qū)內有offset保證局部有序
1.如果topic只有 一個分區(qū)可以實現全局有序
2.寫數據的時候指定分區(qū)編號,只想一個分區(qū)內寫數據
Kafka如何保證自身數據安全
多副本機制
生產者和消費者跟leader副本進行讀寫
follower副本跟leader副本同步數據
且讀寫的內容只能在hw高水位線之前
副本同步機制
為什么會存在同步?因為讀寫只跟leader副本打交道。所以follower副本需要同步數據。
副本集合概念:
AR 該分區(qū)的所有副本 ALL
-
ISR 所有副本中處在同步狀態(tài)的 健康良好的 IN Sync
只有ISR中的副本才有選舉資格 成為新的leader 優(yōu)先順序 從左往右誰來負責leader副本選舉? kafka中主角色controller
誰來kafka主角色controller選舉呢? 通過zk集群選舉?!九R時節(jié)點 監(jiān)聽 唯一性】 -
OSR 非同步狀態(tài)的 Out Sync
正常情況下 OSR集合中應該是空的 每個副本都應該處于健康的狀態(tài)
ISR同步超時 就會被打入OSRAR=ISR+OSR 名詞: LSO start 每個副本的第一個消息offset 正常是0。如果開啟了刪除清理 之前的數據就會被刪除 LEO end 每個副本的【下一個待寫入】的offset值 HW 高水位線 只有它之前的消息才能被消費者拉取消費 hw=min(leo) 類似于木桶效應
Producer生產者如何保證生產的數據不丟失\不重復
-
如何保證kafka數據不丟失
ack校檢和重試機制- ACK級別
0 不管ack 只發(fā)送數據
1 當leader副本保存成功 返回ack給生產者
-1|all 當所有的ISR副本都保存同步成功 返回ack 【最安全 最慢】 - 重試機制
因為網絡質量等偶發(fā)因素導致的消息發(fā)送失敗 可以通過重試機制
如果因為代碼問題 集群環(huán)境問題 重試一百萬次有沒有意義
- ACK級別
-
如何保證數據寫入kafka不重復?
為什么會重復?
1_重試機制,如果前一個ack還沒有返回 生產者認為失敗了基于重試機制重新發(fā)了一遍
2_ack結果延遲 丟失
實際上kafka已經存儲成功了 只不過生產者沒有正確準確的收到ack內部設計了什么機制?
1_冪等性機制 操作一次和操作多次 效果是一樣的。 不跟次數有關。 重復支付 重復提交 常量函數。
2_給每個生產者發(fā)送的消息內部編號 自增id
kafka在保存數據的時候 就會判斷編號 如果已經有了 不保存了直接返回ack
生產者寫入數據分區(qū)規(guī)則
當Producer生產者向Topic隊列中發(fā)送數據時,如何確定發(fā)送到哪個分區(qū)Partition呢?
1.如果用戶指定了分區(qū),就向指定分寫入數據
-
2.如果用戶不指定分區(qū),看是否有自定義分區(qū)規(guī)則
- 2_1 如果沒有指定自定義分區(qū)規(guī)則,按照默認的規(guī)則分區(qū)規(guī)則
如果有key,根據 key的hash值%分區(qū)個數
Utils.murmur2(keyBytes) % numPartitions
計算key哈希值,對partition分區(qū)個數進行取模操作 結果就是分區(qū)編號。
只要key一樣,一定到同一個分區(qū)。如果沒有key:
a_老版本 采用輪詢策略
b_新版本 stickyPartition 黏性策略
if (keyBytes == null) {
return stickyPartitionCache.partition(topic, cluster);
}什么叫做黏性策略呢?
首先判斷當前有沒有partition的連接 如果連接有效 直接使用這個連接
Integer newPart = oldPart;
如果沒有分區(qū)連接,那就隨機選擇一個分區(qū)創(chuàng)建連接 把數據都寫入這個分區(qū)
random- 2_2 如果有自定義分區(qū)規(guī)則,按照自定義分區(qū)規(guī)則分配
- 2_1 如果沒有指定自定義分區(qū)規(guī)則,按照默認的規(guī)則分區(qū)規(guī)則
Consumer消費者如何保證數據不重復不丟失
Kafka記錄了每次消費者消費后的消費記錄
當消費者來消費的時候,只需消費上一次offset+1的數據就可以了
-
消費者消費數據的三種方式
指定topic ????讀取的是指定topic下所有分區(qū)的數據
指定topic partition讀取的是指定topic下的某個分區(qū)的數據
指定topic partition offset讀取的是指定topic下 指定分區(qū)的 某個offset開始
訂閱主題 subscribe 消費該主題的所有分區(qū)數據
訂閱主題指定分區(qū) assign 消費指定主題分區(qū)的數據
精準消費 定位消費 seek 消費指定主題分區(qū) 指定偏移量消費
需要先訂閱topic 和 分區(qū),然后才能seek 偏移量
消費者開始消費數據時,從哪里開始消費
- step1: 第一次消費規(guī)則 由屬性決定
lastest 從0開始
earliest 從最新的開始(默認)
//設置消費的位置 從哪里開始消費 合法參數:latest | earliest
props.setProperty(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG,"earliest");
step2:第二次及以后 從上一次消費完的offset +1位置開始消費
以上成為消費記錄,那么kafka如何保存消費記錄的呢?
消費者內存中 自己維護 程序不斷 不重啟的情況下 【優(yōu)先使用】。
持久化存儲在磁盤、存儲介質: 【重啟程序的依據】
存儲kafka中(默認) 自創(chuàng)了主題_consumer_offsets
存儲zk/mysql/redis
內存消費記錄:kafka自己記錄的非常標準,但是程序重啟之后就沒有了,需要從文件當中讀
文件消費記錄:kafka自己有一個topic 專門用來存儲每個消費者消費的offset

offset偏移量管理
消費者消費完的記錄需要提交,怎樣提交?
- 自動提交
- 根據時間周期提交下一下的消費的offset,默認每五秒提交一次
-
風險:
數據丟失
數據重復
image.png
為了防止數據丟失,或者重復消費我們選擇手動提交
- 手動提交offset
先消費數據,然后再提交offset
風險:如果此時我已經消費了兩個分區(qū)的數據,第三個分區(qū)還沒有消費完,程序崩潰了,offset沒有提交,就會導致,下次程序啟動的時候 重復消費數據 - 手動提交--基于分區(qū)提交offset
offsets.put(partition,new OffsetAndMetadata(consumerOffset+1));
把當前分區(qū)消費的最后一條日志的offset +1,提交上去。 -
手動提交分區(qū)offset探秘
image.png
消費者在自己的內存中維護了消費記錄
當內存中有記錄的時候,程序之間從內存當中讀取消費記錄,這個消費記錄是自己維護的正確的
而磁盤中的消費記錄,只有在程序重啟 內存中的消費記錄丟失了 才會根據磁盤去消費
消費者消費數據分配策略
問題:Kafka 消費組Consumer Group中多個消費者Consumer如何消費Topic隊列中數據?
前提-kafka中同一個消費組中的消費者規(guī)則:
一個分區(qū)只能被一個消費者消費
一個消費者可以消費多個分區(qū)
另 一個分區(qū)的內容,可以被不同消費組內的消費者消費
最理想的狀態(tài):消費者和分區(qū) 一對一
策略:
范圍分配
輪詢分配
粘性分配
1_RangeAssignor 分配策略-范圍分配
- Kafka中默認的分配規(guī)則
- 一個topic中所有的分區(qū)按照消費者的個數平均分,多的就分配給編號小的消費者
優(yōu)點:適用于消費topic比較少的情況,分配會比較平均
ex: 一個topic內有七個分區(qū) 有三個消費者c1 c2 c3
c1 (0,1,2) c2(3,4) c3(56)
缺點: 不適應于多個消費者消費多個topic,會造成編號小的負載壓力大的情況
列如:三個消費者 消費三個topic 每個topic有7個分區(qū)會導致
c1 -t1(0,1,2) t2(0,1,2) t3(0,1,2)
c2 -t1(3,4) t2(3,4) t3(3,4)
c3 t1(5,6) t2(5,6) t3(5,6)
2_RoundRobinAssignor 分配策略-輪詢策略
- 給每個Topic和其分區(qū)編號,輪詢分配給消費者
一個消費者分配一個 輪詢分配
適合:所有消費者都訂閱相同的主題。
缺點:如果有消費者故障 或者加入新的消費者 之前全推倒 重新分配

缺點: c1、c2消費第一個topic,c2、c3消費第二個Topic、c3消費第三個Topic,指定消費者消費Topic
會導致c3 (t2-p2,t3-p1-p2-p3)負載過大
3_StickyAssignor 分配策略-粘性策略(推薦)
粘性策略注意針對的是消費過程者,如果有消費者掛掉了.該如何分配其正在消費的分區(qū).
不出故障的時候跟輪詢一樣,出故障之后正常的都不動,輪詢的分配故障后的分區(qū)

