1. 基本概念
術(shù)語 | 解釋 |
---|---|
Producer | |
Consumer | |
Consumer Group | |
Broker | |
Controller | |
Topic | 相同Topic的生產(chǎn)者和消費者進行通信瑟曲。 |
offset | 某個user group在某個partiton中當前已經(jīng)消費到達的位置。 |
Partition | 分區(qū) |
Leader | 負責讀寫指定分區(qū)的節(jié)點 |
Replicas | 復制該分區(qū)log的節(jié)點列表 |
Isr | "in-sync" replicas抚太,當前活躍的副本列表(是一個子集)茫蛹,并且可能成為Leader |
2. 重要配置
2.1 有序性保證
對于有序性要求嚴格的場景憔恳,將 retries
時間設(shè)置為 Broker 主從切換時間,次數(shù)設(shè)置為合適的正數(shù)挥转, 將 max.in.flight.requests.per.connection
設(shè)置為 1海蔽。
2.2 可靠性保證
- 盡量避免單個硬件(電源連接、交換機)故障導致多臺 broker 停止服務(wù)绑谣。
- 假設(shè)每次故障僅會發(fā)生在單臺 broker 的前提下党窜,進行如下設(shè)置:(1)將
request.required.acks
設(shè)置為 -1,等待所有 producer 等待 ISR 中的所有 replica 的 ack借宵。(2)isr replica 的確認幌衣,慎重設(shè)置,設(shè)置過于嚴格導致誤判壤玫。(3)min.insync.replicas:ISR中最少的follower個數(shù)豁护。一般設(shè)置成大于等于 2 的,否則如果最后的一個broker掛了欲间,則數(shù)據(jù)就丟失了楚里。
2.3 分區(qū)再均衡
數(shù)據(jù)之間不存在邏輯上依賴性,寫數(shù)據(jù)庫后寫 zk猎贴,并且采用數(shù)據(jù)庫的 UUID 保證只寫一次腻豌。
1. zookeeper 在 kafka 中起到什么作用
1.1 Controller 選舉
- Controller 是一個特殊的 Broker, 其負責維護所有 Partition 的 leader/follower 關(guān)系。當有 partition 的 leader 掛掉之后嘱能,controller 會重新從同步隊列中選出一個 leader吝梅。
- Zookeeper 負責從 Broker 中選舉出一個作為 Controller, 并確保其唯一性。 同時, 當Controller 宕機時, 選舉一個新的惹骂。
1.2 集群 membership
記錄集群中都有哪些活躍著的Broker苏携。
1.3 Topic 配置
- 記錄有哪些Topic, Topic 都有哪些 Partition,Replica 存放在哪里, Leader 是誰对粪。
1.4 在 consumer group 發(fā)生變化時進行 rebalance右冻。
1.5 配額(0.9.0+)
- 記錄每個客戶能夠讀寫的數(shù)據(jù)量。
1.6 ACLs(0.9.0+)
- 記錄對Topic 的讀寫控制著拭。
1.7 high-level consumer(已廢棄)
- 記錄consumer group 及其成員和offset 信息纱扭。
2. kafka 在 zookeeper 上創(chuàng)建的目錄結(jié)構(gòu)
詳細內(nèi)容參考鏈接:
kafka筆記-Kafka在zookeeper中的存儲結(jié)構(gòu)【轉(zhuǎn)】
注冊的節(jié)點如下:
consumers、admin儡遮、config乳蛾、controller、brokers、controller_epoch
-
topic 注冊信息
/brokers/topics/[topic]:存儲某個 topic 的 partitions 所有分配信息
-
partition狀態(tài)信息
/brokers/topics/[topic]/partitions/[0...N] 其中[0..N]表示partition索引號
/brokers/topics/[topic]/partitions/[partitionId]/state
-
Broker注冊信息
/brokers/ids/[0...N]
每個broker的配置文件中都需要指定一個數(shù)字類型的id(全局不可重復),此節(jié)點為臨時znode(EPHEMERAL)
-
Controller epoch
/controller_epoch -> int (epoch)
此值為一個數(shù)字,kafka集群中第一個broker第一次啟動時為1肃叶,以后只要集群中center controller中央控制器所在broker變更或掛掉蹂随,就會重新選舉新的center controller,每次center controller變更controller_epoch值就會 + 1
-
Controller注冊信息
/controller -> int (broker id of the controller)
存儲center controller中央控制器所在kafka broker的信息因惭。這個值默認是 1岳锁,當 controller 節(jié)點掛掉后重新選舉 controller 后,值會 +1 Consumer注冊信息
/consumers/[groupId]/ids/[consumerIdString]
每個consumer都有一個唯一的ID(consumerId可以通過配置文件指定,也可以由系統(tǒng)生成),此id用來標記消費者信息-
Consumer owner
/consumers/[groupId]/owners/[topic]/[partitionId] -> consumerIdString + threadId索引編號
記錄當前組下每個 topic 的 partionId 被哪個消費者的線程消費蹦魔。
3. kafka 中的控制器 controller 的作用
Kafka集群中的其中一個 Broker 會被選舉為Controller激率,主要負責 Partition 管理和副本狀態(tài)管理(當 partition leader 掛掉時,會從 follower 中選出一個 leader)勿决,也會執(zhí)行類似于重分配 Partition 之類的管理任務(wù)柱搜。如果當前的 Controller 失敗,會從其他正常的 Broker 中重新選舉 Controller剥险。
4. kafka consumer 均衡算法
當一個group中,有consumer加入或者離開時聪蘸,會觸發(fā)partitions均衡。均衡的最終目的表制,是提升topic的并發(fā)消費能力健爬。
- 假如 topic1 具有如下 partitions: P0,P1,P2,P3
- 假如 group 中有如下 consumer: C0,C1
- 首先根據(jù) partition 索引號對 partitions 排序: P0,P1,P2,P3
- 根據(jù)(consumer.id + '-'+ thread序號)排序: C0,C1
- 計算倍數(shù): M = [P0,P1,P2,P3].size / [C0,C1].size,本例值 M = 2 (向上取整)
- 然后依次分配 partitions: C0 = [P0,P1],C1=[P2,P3]么介,即 Ci = [P(i * M),P((i + 1) * M -1)]
5. kafka 數(shù)據(jù)高可用的原理是什么
一致性定義:若某條消息對Consumer可見,那么即使Leader宕機了,在新Leader上數(shù)據(jù)依然可以被讀到
HighWaterMark簡稱HW: Partition的高水位娜遵,取一個partition對應的ISR中最小的LEO作為HW,消費者最多只能消費到HW所在的位置壤短,另外每個replica都有highWatermark设拟,leader和follower各自負責更新自己的highWatermark狀態(tài),highWatermark <= leader. LogEndOffset
對于Leader新寫入的msg久脯,Consumer不能立刻消費纳胧,Leader會等待該消息被所有ISR中的replica同步后,更新HW,此時該消息才能被Consumer消費,即Consumer最多只能消費到HW位置
這樣就保證了如果Leader Broker失效,該消息仍然可以從新選舉的Leader中獲取帘撰。對于來自內(nèi)部Broker的讀取請求,沒有HW的限制跑慕。同時,Follower也會維護一份自己的HW,Folloer.HW = min(Leader.HW, Follower.offset)
6. kafka 的數(shù)據(jù)可靠性保證
當Producer向Leader發(fā)送數(shù)據(jù)時,可以通過acks參數(shù)設(shè)置數(shù)據(jù)可靠性的級別
- 0: 不論寫入是否成功,server不需要給Producer發(fā)送Response,如果發(fā)生異常,server會終止連接,觸發(fā)Producer更新meta數(shù)據(jù);
- 1: Leader寫入成功后即發(fā)送Response,此種情況如果Leader fail,會丟失數(shù)據(jù)
- -1: 等待所有ISR接收到消息后再給Producer發(fā)送Response,這是最強保證
僅設(shè)置acks=-1也不能保證數(shù)據(jù)不丟失,當Isr列表中只有Leader時,同樣有可能造成數(shù)據(jù)丟失。要保證數(shù)據(jù)不丟除了設(shè)置acks=-1, 還要保證ISR的大小大于等于2,具體參數(shù)設(shè)置:
1.request.required.acks:設(shè)置為-1 等待所有ISR列表中的Replica接收到消息后采算寫成功;
2.min.insync.replicas: 設(shè)置為大于等于2,保證ISR中至少有兩個Replica
注意:Producer要在吞吐率和數(shù)據(jù)可靠性之間做一個權(quán)衡
7. kafka partition 分區(qū)的策略是什么
消息發(fā)送到哪個分區(qū)上摧找,有兩種基本的策略核行,一是采用 Key Hash 算法,一是采用 Round Robin 算法蹬耘。另外創(chuàng)建分區(qū)時芝雪,最好是 broker 數(shù)量的整數(shù)倍,這樣才能是一個 Topic 的分區(qū)均勻的分布在整個 Kafka 集群中综苔。
默認情況下惩系,Kafka 根據(jù)傳遞消息的 key 來進行分區(qū)的分配位岔,即 hash(key) % numPartitions。
如果發(fā)送消息時沒有指定key蛆挫,那么 Producer 將會把這條消息發(fā)送給隨機的一個 Partition赃承。但是代碼層面的邏輯并不完全是這樣妙黍。首先看看Kafka有沒有緩存的現(xiàn)成的分區(qū)Id悴侵,如果有的話直接使用這個分區(qū)Id。如果沒有的話拭嫁,找出所有可用分區(qū)的leader所在的broker可免,從中隨機挑一個并放到緩存中,下次就直接從緩存中拿這個 partition id做粤。注意這個緩存是每隔一段時間就會被清空的浇借。這么做的目的是為了減少服務(wù)器端的sockets數(shù)。
8. Kafka Producer是如何動態(tài)感知Topic分區(qū)數(shù)變化
過一定的時間(topic.metadata.refresh.interval.ms參數(shù)決定)才知道分區(qū)數(shù)改變的怕品。
10. kafka 如何實現(xiàn)高吞吐量
參考資料
- Kafka入門經(jīng)典教程
- Kafka 監(jiān)控工具
- kafka的數(shù)據(jù)副本機制(詳細解讀)
- kafka 權(quán)威指南
- 《Kafka參數(shù)調(diào)優(yōu)實戰(zhàn)妇垢,看這篇文章就夠了!》
- 簡歷寫了會Kafka肉康,面試官90%會讓你講講acks參數(shù)對消息持久化的影響