1 kafka consumer消費位移為什么從zookeeper改到kafka內部主題__consumer_offsets中?
kafka 0.9版本之前使用zookeeper保存offset,之后版本使用內部主題,網上有一個答案是kafka offset維護方式
主要的點是zookeeper引入了多余的網絡通訊,broker需要多余的連接來訪問offset,存儲在broker端,可以減少該部分的IO損耗,簡化設計
2 kafka是如何使用isr的?
kafka通過isr機制來維持數據的一致性,isr即in-sync replica,跟isr相關的參數有acks、min.insync.replicas、replica.lag.time.max.ms、replica.lag.max.messages(已移除)
isr由leader動態維護,當副本節點落后leader太多或者超時未請求同步時,將副本剔除isr集合,待副本同步后,會重新加入isr集合
acks:由客戶端配置,表示多少個副本收到消息后,才認為消息寫入成功,0相當于異步,all,相當于同步,生產環境中需要兼顧可用性和性能,一般配置acks=1
min.insync.replicas:控制消息成功寫入最小副本數
replica.lag.max.messages(已移除):isr集合中副本落后leader的最大值,因為生產環境中很難定義這個閾值,0.9版本后移除了該參數
replica.lag.time.max.ms:isr集合中副本落后leader的最大時間間隔
3 kafka如何實現exactly-once語義?
exactly-once解釋,即使生產者產生重復的消息,消費者也應該只收到一次消息,這也就是所謂的冪等
配置冪等通過配置enable.idempotence=true實現
實現:producer消息是分批發送,每個分批都有一個序號(單調遞增),broker追蹤分區的最大序號,當出現序號相等或者小于最大序號的,不寫入topic
4 kafka使用isr來選主,具體選主流程是什么樣的,是另外一個raft嗎?還是有其他約束?
答:
1、大數據常用的選主機制
leader的選擇方法非常多,大數據領域常用的的選舉方法有如下集中
(1)Zab(zookeeper使用)
a、快速leader選舉(leader election)
b、發現或者版本建立(epoch establish)
c、同步(follower從leader同步數據和狀態)
d、廣播(leader廣播數據或狀態到follower)
例如有3個節點需要選舉leader,編號為1,2,3. 先啟動1,選擇自己為leader,然后啟動2,首先也選擇自己為leader。由于1,2都沒有過半,選擇編號大的為leader,所以1,2都選擇2為leader。然后3啟動后發現1,2都已經協商好且數量過半,于是3也選擇2為leader,此時leader選擇結束。
因為zab協議需要選擇過半以上才能被選舉為leader,所以zab協議需要奇數個機器參與選舉(1,3,5,7一般不超過7個,因為zk一般同步元數據,所以負載不是很高,zk管理的節點通信負載才比較高,5或7個一般能處理大量的集群),一般為第二個節點啟動后被選擇為leader。
zookeeper進行選舉時,有兩個典型場景
1 啟動時leader選舉
2 運行過程中leader選舉
(2)Raft協議
相關角色說明
leader:處理所有客戶端交互,日志復制等,一般只有一個leader
Follower:類似選民,完全被動
Candidate:候選人,可以為選為一個新的領導,由管理員配置
啟動時在集群中指定一些機器為candidate,然后candidate開始向其他機器(尤其是follower)拉票,當某一個candidate的票數超過半數,它就成為leader(同美國總統選舉)。
兩種選擇算法的區別聯系
(1)他們都是Paxos算法的變種。
(2)與zab協議不同的是,zab的每一個節點都有被選為leader的協議,raft協議必須從候選人中選擇為leader。
2、常用選主機制的缺點
最簡單的方式
由于kafka集群依賴zookeeper集群,所以最簡單直觀的方案是:所有的follower都在zookeeper上設置一個watch,一旦leader宕機,其對應的ephemeral znode(臨時節點)會自動刪除,此時所有follower都嘗試創建該節點,而創建成功者(zookeeper保證只有一個能創建成功)即是新的leader,其他replica即為follower。
該方式有如下缺點:
a、腦裂(split-brain)
這是由于zookeeper的特性引起的,雖然zookeeper能保證所有的watch按順序觸發,但并不能保證同一時刻所有的replica看到的狀態是一樣的,這就可能造成不同的replica的響應不一致;(如由于網絡原因部分選擇的leader已經更新,但是其他follower由于網絡原因沒有看到,部分又選舉出一個leader,導致一個集群出現兩個leader)
b、羊(驚)群效應(herd effect)
如果宕機的哪個broker上的partition比較多,會造成多個watch被觸發,造成集群類大量的調整(向羊群開一槍所有羊群四處奔散,造成網路資源和負載)。
c、zookeeper負載過重:每一個replica都要為此在zookeeper上注冊一個watch,當集群規模增加到幾千個partition時,zookeeper負載會過重。
3、kafka分區的選主機制
kafka如何解決以上選舉機制的
kafka的leader election方案解決了上述問題,它在所有的broker中選出一個controller,所有的partition的leader選舉都有controller決定。controller會將leader的改變直接通過RPC的方式(比zookeeper Queue的方式更高效)通知需要為此作為響應的broker。
原因:
1、不用zk選舉,使用controller(Controller會將leader的改變通過rpc方式通知給follower),沒有zk負載過重問題
2、也沒有注冊watch不會觸發任何事件-驚群效應
3、leader失敗是由一個Controller進行選舉并不會產生任何通信,所以不會有腦裂的情況
問題:
(1)Controller是如何選舉出來的
每一個broker都會在Controller path(/controller)上注冊一個watch。當前controller失敗時,對應的Controller path會自動消失(臨時節點)。此時該watch被觸發,所有活著的broker都會去競選成為新的Controller(創建新的controller path),但是只有一個會競選成功。競選成功者成為新的leader。競選失敗則重新在新的Controller path上注冊watch,因為zk的watch是一次性的,被觸發一次之后即失效,所以需要重新注冊。
(2)如何使用Controller進行partition選舉
a、從zk中讀取當前分區的所有ISR(in-sync-replicas)集合
b、調用配置的分區算法選擇分區的leader
kafka選擇分區算法:
i、NoOpLeaderSelector–偏愛分區(SR中的第一個),并將leader發送給為此做出改變的broker,
ii、offlinePartitionLeader–也是選擇偏愛分區作為leader
iii、reassignedPartitionLeader
iii、preferredReplicaPartitionLeader
iiii、ControlledShutdownLeader
上面五中算法都使用偏愛分區作為leader,區別是選擇leader之后所做的操作不同。