一、概述
(一)、kafka的定義
1、定義
1)kafka傳統的定義:kafka是一個分散式的基於釋出/訂閱模式的訊息佇列,主要用於大資料實時處理領域
2)kafka最新的定義:kafka是一個開源的分散式事件流平臺(event stream platform),主要用高效能資料管道,流分析,資料整合和關鍵任務等領域
2、訊息佇列
目前市面上大部分公司採用的訊息佇列主要有kafka,activeMQ,rabbitMQ,rocketMQ等。kafka作為訊息佇列,主要應用於大資料場景下,而在Javaee開發中更多采用的是activeMQ,rabbitMQ,rockectMQ等。
3、訊息佇列的應用場景
傳統的訊息佇列的主要應用場景包括:緩衝/削峰,解耦和非同步通訊
緩衝/削峰:在實際的應用系統中,如果資料生產端(比如其前端)的資料產生的速率與資料處理端(服務端)的資料處理速率相當或小於時,整合系統執行就不會有很大的壓力。但是當系統上了個秒殺活動或者雙11活動到來,前端使用者猛增,資料率隨之也會增加數倍,甚至是數十倍。但是服務端需要對資料進行處理,持久化等操作,處理速率必然跟不上資料產生的速度,久而久之系統就會產生資料積壓,最終就有可能導致系統的崩潰。在資料生產端和處理端之間使用訊息佇列就可以解決這種問題。此時,訊息佇列就發揮了不同系統之間資料的緩衝和削峰的作用。資料生產端將資料傳送到訊息佇列,然後隨即返回響應,這個過程相對來說是非常快的。資料處理端則根據自己的處理速度從訊息佇列中拉取資料。示意圖如下:
不使用訊息佇列的情況
使用訊息佇列的情況
解耦:允許獨立的擴充和修改兩邊的處理過程,但兩邊需要確保使用相同的介面約束。
非同步通訊:將處理的使用者資料寫入到訊息佇列中,並立即返回處理結果,佇列中資料由另一個執行緒拉取出來做響應的處理。下面是使用者註冊,並把註冊成功的訊息傳送到使用者手機上的同步處理和非同步處理的流程。
(二)、kafka基礎架構
1、訊息佇列的兩種模式
1)點對點模式
-
-
-
- 消費者主動拉取資料,資料消費完後就會在佇列中刪除
-
-
2)釋出/訂閱模式
-
-
-
- 可以有有多個主題(topic)
- 消費者拉取資料消費完後,不刪除資料
- 每個消費者相互獨立,都可以消費到資料
-
-
2、基礎架構
1)producer:訊息生產者,就是向broker傳送訊息的客戶端
2)consumer:訊息消費者,就是從broker拉取資料的客戶端
3)consumer group:消費者組,由多個消費者consumer組成。消費者組內每個消費者負責消費不同的分割槽,一個分割槽只能由同一個消費者組內的一個消費者消費;消費者組之間相互獨立,互不影響。所有的消費者都屬於某個消費者組,即消費者組是一個邏輯上的訂閱者。
4)broker:一臺伺服器就是一個broker,一個叢集由多個broker組成,一個broker可以有多個topic。
5)topic:可以理解為一個佇列,所有的生產者和消費者都是面向topic的。
6)partition:分割槽,kafka中的topic為了提高擴充性和實現高可用而將它分佈到不同的broker中,一個topic可以分為多個partition,每個partition都是有序的,即訊息傳送到佇列的順序跟消費時拉取到的順序是一致的。
7)replication:副本。一個topic對應的分割槽partition可以有多個副本,多個副本中只有一個為leader,其餘的為follower。為了保證資料的高可用性,leader和follower會盡量均勻的分佈在各個broker中,避免了leader所在的伺服器當機而導致topic不可用的問題。
8)leader:多個副本的主副本,生產者傳送的資料和消費者消費的資料都是通過leader進行處理的。
9)follower:多個副本中除了leader副本,其餘的均為follower副本,也即從副本。從副本不會和生產者和消費者提供服務,而是實時同步主副本的資料。當主副本當機後,通過一定演算法選舉出新的從副本成為主副本,繼續為生產者和消費者提供服務。
(三)、kafka常用命令列操作
1、主題相關
引數 | 描述 |
--bootstrap-server <String: server toconnect to> | 連線的 Kafka Broker 主機名稱和埠號。 |
--topic <String: topic> | 操作的 topic 名稱。 |
--create | 建立主題。 |
--delete | 刪除主題。 |
--alter | 修改主題。 |
--list | 檢視所有主題。 |
--describe | 檢視主題詳細描述。 |
--partitions <Integer: # of partitions> | 設定分割槽數。 |
--replication-factor<Integer: replication factor> | 設定分割槽副本。 |
--config <String: name=value> | 更新系統預設的配置。 |
2、生產者相關
引數 | 描述 |
--bootstrap-server <String: server toconnect to> | 連線的 Kafka Broker 主機名稱和埠號。 |
--topic <String: topic> | 操作的 topic 名稱。 |
3、消費者相關
引數 | 描述 |
--bootstrap-server <String: server toconnect to> | 連線的 Kafka Broker 主機名稱和埠號。 |
--topic <String: topic> | 操作的 topic 名稱。 |
--from-beginning | 從頭開始消費。 |
--group <String: consumer group id> | 指定消費者組名稱。 |
二、生產者
(一)、重要引數列表
引數名稱 |
描述 |
bootstrap.servers |
生產者連線叢集所需的 broker 地 址 清 單 。可以設定 1 個或者多個,中間用逗號隔開。注意這裡並非需要所有的 broker 地址,因為生產者從給定的 broker裡查詢到其他 broker 資訊。 |
key.serializer 和 value.serializer |
指定傳送訊息的 key 和 value 的序列化型別。一定要寫全類名。 |
buffer.memory |
RecordAccumulator 緩衝區總大小,預設 32m。 |
batch.size |
緩衝區一批資料最大值,預設 16k。適當增加該值,可以提高吞吐量,但是如果該值設定太大,會導致資料傳輸延遲增加。 |
linger.ms |
如果資料遲遲未達到 batch.size,sender 等待 linger.time之後就會傳送資料。單位 ms,預設值是 0ms,表示沒有延遲。生產環境建議該值大小為 5-100ms 之間。 |
acks |
|
max.in.flight.requests.per.connection |
允許最多沒有返回 ack 的次數,預設為 5,開啟冪等性要保證該值是 1-5 的數字。 |
retries |
當訊息傳送出現錯誤的時候,系統會重發訊息。retries表示重試次數。預設是 int 最大值,2147483647。如果設定了重試,還想保證訊息的有序性,需要設定MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION=1否則在重試此失敗訊息的時候,其他的訊息可能傳送成功了。 |
retry.backoff.ms |
兩次重試之間的時間間隔,預設是 100ms。 |
enable.idempotence |
是否開啟冪等性,預設 true,開啟冪等性。 |
compression.type |
生產者傳送的所有資料的壓縮方式。預設是 none,也就是不壓縮。支援壓縮型別:none、gzip、snappy、lz4 和 zstd。 |
(二)、傳送流程以及傳送API
1、傳送流程
(三)、分割槽
1、分割槽的好處
-
-
- 便於合理使用儲存資源。每一個partition儲存在不同的broker上面,可以把海量的資料切割成更小資料儲存在不同的broker上。合理是分配分割槽的任務,可以實現負載均衡效果,避免單機資料量太大而導致的壓力。
- 提高並行度。生產者可以以分割槽為單位傳送資料;消費者可以以分割槽為單位消費資料。
-
2、分割槽策略
1)、預設分割槽策略:DefaultPartitioner
-
-
- 若生產者傳送資料時指明partition,那麼就會將該資料傳送指定的分割槽,比如partition=0,則資料傳送到第零個分割槽上
- 若沒有指明partition,但是有key的情況下,用key的hashcode值與該topic對應的partition的數量進行取餘得到partition,然後將資料傳送到該分割槽上。比如:key的hashcode值為5,topic對應的分割槽數為3,那麼 5 % 3 = 2,所以該資料應該傳送到第二個分割槽。
- 既沒有指定partition和key,kafka採用粘性分割槽器,會隨機選擇一個分割槽,然後儘可能使用該分割槽,指導該分割槽batch-size滿了或已完成,然後再隨機尋找另一個分割槽(與當前的分割槽不一樣)。比如:這次隨機到分割槽0,等當前批次滿了或者linger.ms時間已到,kafka再隨機一個分割槽,如果仍然隨機到分割槽0則繼續隨機。
-
2)自定義分割槽器
在實際的企業應用中,可能會有不用的場景,預設的分割槽器無法滿足需求,那麼就需要自定也分割槽器來滿足需求,比如某個分割槽的伺服器效能比較好,另一個是比較久的伺服器,效能相對差一點,那麼就需要通過自定義分割槽器讓更多的資料向效能更好的分割槽傾斜。
自定義分割槽器的實現:第一,定義類實現 Partitioner 介面。第二,重寫partition()方法。第三,在生產者配置中指定自定義的分割槽器。
(四)、提高生產者的吞吐量
要想更好的提高生產者的吞吐量,則必須先了解生產者傳送資料的流程,具體流程可以看靠(一)的介紹。以下是提高生產者的吞吐量的建議。
- 修改batch.size的大小。batch.size預設大小為16k,提高批次大小可以一定程度提高吞吐量。這就好比用小卡車拉貨物和用大卡車拉貨物,小卡車單位時間內不能一次拉完貨物,那麼來回就需要消耗額外時間,而大卡車一次性把貨物拉走,那麼就節省了來回的時間。
- 修改linger.ms的時間,預設為0,即直接傳送資料,一般設定為5-100ms,通過設定延遲時間一次性可以傳送更多的資料。
-
修改compression.type的資料壓縮型別,預設snappy。根據不同的業務場景選擇不同的資料壓縮方法,提高資料壓縮率。kafka提供的壓縮型別有:gzip,snappy,lz4,zstd。
-
修改RecordAccumulator緩衝區的大小。預設32m,增加緩衝區大小可以那麼每個batch.size的值就更大,每次傳送的資料更多。
(五)、資料可靠性
資料的可靠性是指producer傳送資料到kafka收到應答後,該資料都能成功落盤,那麼這次傳送是可靠的。但是,為了適應不用的應用場景以及實現高可用,kafka會將資料備份到不同的副本當中,在資料同步的過程中如果出現的故障,那麼就有可能出現資料丟失,重複情況。想要弄清楚kafka資料可靠性,就必須先要了解kafka中ACK的應答原理。
1、ACK應答原理
ACK應答是指在leader分割槽接收到生產者的資料後,何時對生產者做出應答的策略。ACK可選的值有0,1,-1三個,可以在生產者的配置項 acks 中設定,ACK設定不同,對生產者做出應答的時機也不同。
ACK=0:可靠性級別最低。leader收到生產者資料後不需要等資料落盤,立即對生產者做出應答。生產者收到應答後認為leader已成功接收資料,因此不需要再發當前資料了。但是,如果leader在將記憶體中的資料落盤時突然出現故障,那麼這條資料因為沒有儲存到磁碟中而導致資料的丟失。
ACK=1:可靠性級別較高。leader收到生產者的資料並將資料落盤後,對生產者做出應答。生產者收到應答後繼續傳送其他資料。如果leader做出應答並且follower未同步到該資料時,leader出現故障。kafka會重新在follower中選出新的leader,而新的leader心有同步到資料,生產者也不會再發該資料,因此導致該資料的丟失。
ACK=-1(all):可靠性級別最高,kafka的acks預設值。leader收到資料並落盤,並且確認所有follower收到資料後再給生產者應答。此時,所有分割槽副本都有該資料了,即使任意分割槽出現故障資料仍然是完整的。
(六)、資料去重
1、資料重複原因
在使用kafka時為了保證資料的高可靠性,我們一般都會將應答級別設定為-1(all),即leader的ISR列表的follower均收到資料後再應答。非常不幸的是,leader在收到所有的follower的確認後發生故障,所有的分割槽均已儲存到磁碟中,但是生產者沒有收到應答,認為leader沒有收到生產者傳送請求,於是嘗試重新傳送請求。由於leader發生故障,kafka重新選舉leader,生產者將資料再一次傳送到新的leader上,所以造成的資料重複。
2、資料去重
kafka 0.11之後引入了冪等性和事務兩大特性。利用這兩個特性可解決資料重複的問題。
1)資料傳遞語義
-
-
-
-
- 至少一次(At Least Once):ACK級別為-1 + 分割槽副本大於等於2 + ISR中應答的最小副本數量大於等於2;
- 至多一次(At Most Once):ACK應答級別為 0;
-
-
-
At Least Once可以保證資料不丟失,但不能保證資料重複。
At Most Once 可以保證資料不重複,但不能保證資料不丟失。
2)冪等性的原理
冪等性:是指無論producer傳送多少條重複的資料,broker端都只會持久化一條資料,保證了資料不重複。
資料重複的判斷依據:具有<PID, Partition, SeqNumber>相同主鍵的訊息提交時,Broker只會持久化一條。其中PID是Kafka每次重啟都會分配一個新的;Partition 表示分割槽號;Sequence Number是單調自增的。
從資料重複判斷依據來看,冪等性只能保證單分割槽會話內資料不重複。
開啟冪等性:enable.idempotence = true,預設為true。
3)事務
kafka的事務需要跟冪等性配合起來使用。開啟事務就必須開始冪等性。
(七)、資料亂序和有序
1、資料亂序
kafka的producer客戶端在向broker傳送資料時並不是直接將資料傳送出去,而是將資料先快取到本地的雙端快取佇列中,sender執行緒會不斷地檢測快取佇列中地資料,若佇列中地資料達到了設定的(batch.size)值地容量或者達到一定的時間(linger.ms),sender就會建立一個InFlightRequests執行緒,該執行緒負責將資料傳送到broker上。kafka 預設的InFlightRequests是5個,InFlightRequests執行緒傳送資料後不需要broker的應答就可以發下一個資料,因此最多可以一起發5個請求。比如,需要傳送0,1,2,3,4這五個資料依次被髮送出去,但是2這個資料沒有接收成功,客戶端則重新2的資料,此時broker接收到的資料的順序就變為了01342,而非01234。
2、資料有序
1)kafka在1.x之前保證資料單分割槽有序,需要將InFlightRequests執行緒數設定為1個(max.in.flight.requests.per.connection=1)。當執行緒數為1時就能保證broker收到資料確認後再發下一條資料。
2)kafka在1.x以後在未開啟冪等性的情況下,處理流程跟1.x以前的版本一樣。
3)1.x以後在開啟冪等性的情況下,可以將max.in.flight.requests.per.connection設定為小於等於5。原因是,Kafka服務端會快取最近發過來的後設資料,等快取滿了5個後就會對這些後設資料進行排序,這樣就可以保證資料有序了。
三、broker
(一)、工作流程
1、重要引數
引數名稱 | 描述 |
replica.lag.time.max.ms | ISR 中,如果 Follower 長時間未向 Leader 傳送通訊請求或同步資料,則該 Follower 將被踢出 ISR。該時間閾值,預設 30s。 |
auto.leader.rebalance.enable | 預設是 true。 自動 Leader Partition 平衡。 |
leader.imbalance.per.broker.percentage | 預設是 10%。每個 broker 允許的不平衡的 leader的比率。如果每個 broker 超過了這個值,控制器會觸發 leader 的平衡。 |
leader.imbalance.check.interval.seconds | 預設值 300 秒。檢查 leader 負載是否平衡的間隔時間。 |
log.segment.bytes | Kafka 中 log 日誌是分成一塊塊儲存的,此配置是指 log 日誌劃分 成塊的大小,預設值 1G。 |
log.index.interval.bytes | 預設 4kb,kafka 裡面每當寫入了 4kb 大小的日誌(.log),然後就往 index 檔案裡面記錄一個索引。 |
2、zookeeper儲存的kafka資訊
3、工作的總流程
① broker啟動,向zookeeper註冊broker節點資訊
② 向zookeeper註冊controller,若註冊成功則該controller負責選舉leader,監聽broker節點等工作
③ 註冊成功的controller開始監聽brokers節點變化
④ 註冊成功的controller舉行leader選舉。按照AR列表優先選取排在前面的節點,若該節點在ISR中存活則成為leader,否則繼續輪詢。例如:AR[0,1,2],ISR[1,2],controller會從broker 0 開始輪詢,發現ISR中並沒有0,那麼繼續輪詢到1,發現ISR有1則1成功leader。
⑤ 註冊成功的controller將選舉結果寫入到zookeeper中,同時其他controller也監聽該資訊,等leader故障後方便立即上位成為新的leader。
⑥ 加入leader掛掉了,controller監聽到節點傳送變化,開始拉取ISR資訊,然後開始重新選擇leader。
(二)、副本
1、基本資訊
-
-
- 作用:提高資料可用性
- Kafka預設的副本數為1,生產環境可設定為2,保證資料可靠性。不建議設定太多的副本,一者增加磁碟儲存空間,二者增加副本同步時的網路開銷,影響效率。
- 副本分為 leader 和follower。leader只有一個,其餘的為follower。生產者的資料發給的是leader,消費者消費的訊息也是來自leader的。follower同步leader的訊息。
- AR:分割槽中所有副本的總和。
- ISR:分割槽中能夠和leader保持同步的副本,包括leader本身。如果follower長時間未向leader傳送通訊資訊或同步請求,那麼該follower就會從ISR中移除。leader掛了後ISR中的follower重新選舉leader。
- OSR:分割槽中跟leader同步資訊差距較大的副本或者是掛了的副本。
- AR = ISR + OSR
-
2、leader選舉流程
Kafka叢集中有一個會被選舉為controller leader,選舉方式搶佔式,誰先搶佔到zookeeper的節點,誰就能成為leader。該controller負責Kafka叢集broker的上下線,topic分割槽副本的分配和leader選舉等工作。
3、leader和follower故障處理
LEO(log end offset):每個副本的最後一個offset,即最新offset + 1。
HW(high watermark):所有副本中最小的LEO。
1)leader發生故障
leader發生故障後,kafka會從ISR中重新選舉出新的leader
為保證多副本之前的資料一致性,其餘的follower會先將自己高於HW的資料截掉,然後同步新leader的資料。
2) follower發生故障
follower發生故障後會被臨時踢出ISR。
此時leader和follower繼續接收資料。
等follower恢復後讀取儲存在磁碟的HW,並將log檔案中高於HW部分的資料擷取丟棄,從HW位置開始同步leader的資料。
follower同步到LEO大於等於分割槽的HW時,kafka就將該副本重新加入到ISR中。
4、副本分配
1)儘量將所有副本平均地分配到所有地broker上。
2)每個broker分配到地leader儘可能一樣多。
3)leader和follower儘可能地分配到不同地broker上。
5、leader分割槽自平衡
正常情況下,Kafka本身會盡可能地將leader分割槽均勻地分佈到各個機器上,這樣使得每個機器的讀寫吞吐量比較均勻。但是,如果當leader分割槽故障後,另一個follower就會迅速上位並且承擔之前的leader的工作,讀寫請求的壓力就會上升,造成叢集負載不平衡。kafka允許的每個broker不平衡的比率預設為10%,如果超過了這個值就會觸發leader分割槽平衡。
相關引數:
引數名稱 | 描述 |
auto.leader.rebalance.enable | 預設是 true。 自動 Leader Partition 平衡。生產環境中,leader 重選舉的代價比較大,可能會帶來效能影響,建議設定為 false 關閉。 |
leader.imbalance.per.broker.percentage | 預設是 10%。每個 broker 允許的不平衡的 leader的比率。如果每個 broker 超過了這個值,控制器會觸發 leader 的平衡。 |
leader.imbalance.check.interval.seconds | 預設值 300 秒。檢查 leader 負載是否平衡的間隔時間。 |
(三)、資料儲存
1、儲存機制
Kafka中topic是邏輯概念,但是分割槽partition是物理概念,生產者傳送的資料都是儲存在partition中的,每個partition中都有一個log檔案,資料實際都是儲存在log檔案中,生產者生產的資料都會最佳到該log檔案的末端。為防止log檔案過大導致資料檢索過慢,kafka將log檔案進行切片,每個片成為segment,每個segment中包括“.index”檔案,“.log”檔案和“.timestamp”等檔案。
log檔案:儲存實際資料的檔案。
index檔案:偏移量索引檔案,檔案為segment第一個資料offset值。index檔案是一個稀疏索引,每往log檔案中寫入4kb的資料才向index檔案中寫入一條索引。
timestamp檔案:時間戳索引檔案,檔名為segment第一條資料的offset值。
2、資料檔案清楚策略
Kafka提供的檔案刪除策略有delete和compact兩種。
delete策略:將過期資料刪除
log.cleanup.plocy = delete 所有資料啟用刪除策略
-
-
-
- 基於時間刪除,預設開啟。以segment中所有記錄中最後記錄的時間戳作為該檔案的時間戳。
- 基於大小刪除,預設關閉。超過設定的所有日誌總大小,刪除最早的segment。
-
-
compact日誌壓縮:對於相同key的不同value值,只保留最後一個value值。壓縮後的offset可能是不連續的。這種策略只適合某些特殊的場景,比如key儲存的是使用者id,value儲存的使用者資訊,通過壓縮策略就能將舊的使用者資料刪除,只保留新的使用者資訊。
(四)、高效讀寫資料
1、Kafka是基於分散式叢集,採用分割槽技術,資料讀寫並行度高。
2、讀資料採用稀疏索引,消費者能夠快速定位消費的資料。
3、順序寫磁碟,producer生產資料只是在log檔案的末端追加資料,因此寫磁碟的速度很快。
4、Kafka以來系統底層的pagecache技術和零拷貝技術,能夠提高磁碟資料讀寫速度。
四、消費者
(一)、重要引數
引數名稱 | 描述 |
bootstrap.servers | 向 Kafka 叢集建立初始連線用到的 host/port 列表。 |
key.deserializer 和 value.deserializer | 指定接收訊息的 key 和 value 的反序列化型別。一定要寫全 類名。 |
group.id | 標記消費者所屬的消費者組。 |
enable.auto.commit | 預設值為 true,消費者會自動週期性地向伺服器提交偏移量。 |
auto.commit.interval.ms | 如果設定了 enable.auto.commit 的值為 true, 則該值定義了消費者偏移量向 Kafka 提交的頻率,預設 5s。 |
auto.offset.reset |
當 Kafka 中沒有初始偏移量或當前偏移量在伺服器中不存在如,資料被刪除了),該如何處理? earliest:自動重置偏移量到最早的偏移量。 latest:預設,自動重置偏移量為最新的偏移量。 none:如果消費組原來的(previous)偏移量存在,則向消費者拋異常。 anything:向消費者拋異常。 |
offsets.topic.num.partitions | __consumer_offsets 的分割槽數,預設是 50 個分割槽。 |
heartbeat.interval.ms | Kafka 消費者和 coordinator 之間的心跳時間,預設 3s。該條目的值必須小於 session.timeout.ms ,也不應該高於session.timeout.ms 的 1/3。 |
session.timeout.ms | Kafka 消費者和 coordinator 之間連線超時時間,預設 45s。超過該值,該消費者被移除,消費者組執行再平衡。 |
(二)、消費方式
1、pull(拉)模式
consumer主動拉取服務端的資料。Kafka採用這種方式。
優點:consumer根據自己的處理能力拉取服務端的資料。
缺點:當服務端沒有資料時,consumer仍然不斷從服務端拉取資料,會消耗consumer一定的資源。
2、push(推)模式
服務端主動推訊息給consumer。
優點:服務端只要有資料是才會推資料給consumer。
缺點:服務端傳送訊息的速率很難適應所有consumer處理訊息的速率。
(三)、消費者消費流程
1、總體消費流程
1)消費者通過offset拉取broker中指定位置的訊息。offset則儲存在系統主題中,系統主題儲存在磁碟中,所以即使服務端出現故障或重啟等能夠按上次消費的位置開始消費。
2)一個消費者可以消費多個分割槽的資料。
3)每個分割槽的資料只能由消費者組的一個消費者消費。
2、消費者組
1)消費者在消費訊息時必須指定消費者組id(group.id),具有相同的group.id組成一個消費者組。
2)消費者組的消費者消費不同分割槽的資料。一個分割槽只能由一個消費者消費。
3)消費者組之間相互獨立,互不影響。
4)消費者組的消費者數量應小於等於分割槽數量,若消費者數量大於分割槽數,多餘的消費者則不會消費訊息。
5)消費者消費訊息後傳送offset給服務端。
3、消費者初始化流程
(四)、分割槽的分配策略以及再平衡
1、Range分割槽策略
首先對同一個topic的分割槽對分割槽序號進行排序,然後消費者按照字母排序,利用分割槽數除以消費者數量得出每個消費者平均消費分割槽數,若剩餘多的則按順序消費。
注意:當topic數量比較多時,使用Range分割槽策略會導致排在前面的消費總是分配更多的消費者,造成資料傾斜。
再平衡策略:當某個消費者掛了,Kafka會將該消費者的任務全部交給正常消費的消費者。
2、RoundRobin分割槽策略
先進行排序,然後消費依次輪詢消費分割槽資料。
再平衡:觸發再平衡後,將故障的消費者的任務輪詢交給正常消費的消費者。
3、Sticky分割槽策略
粘性分割槽是 Kafka 從 0.11.x 版本開始引入這種分配策略,首先會盡量均衡的放置分割槽到消費者上面,在出現同一消費者組內消費者出現問題的時候,會盡量保持原有分配的分區不變化。
再平衡:儘可能均衡的隨機分成 0 和 1 號分割槽資料,分別由 1 號消費者或者 2 號消費者消費。
(五)、offset位置
1、offset的維護
Kafka0.9版本之前,consumer預設將offset儲存在Zookeeper中。
從0.9版本開始,consumer預設將offset儲存在Kafka一個內建的topic中,該topic為__consumer_offsets。
2、offset提交
分為自動提交和手動提交,預設為自動提交
1)自動提交
enable.auto.commit:設定為true
auto.commit.interval.ms:自動提交offset的間隔時間,預設為5s
2)手動提交
enable.auto.commit :設定為false。使用者可以根據具體場景進行提交,更加靈活。手動提交可分為同步提交和非同步提交兩張方式。
3、指定offset消費
當消費者第一次消費或者offset資訊丟失,這是消費者該如何進行消費呢?Kafka提供了三種方式:earliest,latest和none
earliest:自動將offset設定為最開始的位置。
latest:自動將offset設定為最新的offset位置。
none:若沒有找到之前的offset資訊,則會丟擲異常。
4、指定時間消費
消費者根據指定時間(比如1天前)獲取資料,通過broker的時間戳索引檔案查到該時間對應的offset,然後用該offset獲取對應的資料。
(六)、漏消費和重複消費
1、漏消費
先提交offset後處理資料,可能會造成漏消費訊息。一般使用者設定為手動非同步提交offset會引起這種問題。
場景:消費者offset提交方式設定為手動非同步提交,消費者把offset提交出去,但是資料還未落盤,此時消費者掛掉,分割槽已經將最新的offset儲存起來了。消費者重啟後獲取的offset則是最新提交的offset了,造成資料遺漏處理。
2、重複消費
已經消費了訊息,但是沒提交offset。一般消費者設定為自動提交會有這種問題。
場景:消費者設定offset自動提交時間為5s,在第2s時消費者掛掉,在掛掉前已經處理部分資料,但offset沒有提交到broker。消費者重啟後拿到的offset則為舊的offset,之前處理過的資料又被拉取一遍,造成重複消費資料。
(七)、消費者事務
若要保證消費者消費資料時不漏消費,不重複消費,則需要將消費者端在消費訊息和提交offset的操作看作是依次原子操作。
(八)、資料積壓
所謂資料積壓是指broker中儲存大量未消費的訊息。若長時間未消費且觸發了刪除策略,那麼這部分資料就會丟失。可能造成資料積壓的原因有消費者的處理能力不足,分割槽數較少,可適當增加分割槽數量,使分數量等於消費者數量。也可以把消費者每次拉取資料的大小往上調。
五、總結
Kafka憑藉自身優秀的效能和海量資料的處理能力以及資料的可靠性保證,元件在大資料領域佔據主流地位。