爲了保障Prosucer發送的消息能可靠的發送到指定的Topic,Topic的每一個Partition收到消息後,要向Producer發送ACK,若是Produser收到ACK,就會進行下一輪發送,不然重試。緩存
爲了提升消息的可靠性,Kafka每一個Topic的partition都有N個副本(replica)。這N個副本中,其中一個replica是Leader,其餘都是Follower。 Leader負責處理Partition的全部請求,Follower負責同步Leader的數據。 下圖展現了Kafka集羣中的4個Broker,Topic有3個Partition。異步
Partition何時纔會發送ACK呢? 要確保所有的Follower與Leader同步完成以後,Leader才能發送ACK,這樣才能保證Leader掛掉以後,在全部Follower中能選出新的Leader。 可是萬一有一個Follower由於故障,遲遲不能和Leader同步,Leader就得等着它完成同步以後才能發送ACK,怎麼決解呢? 這就引出了ISR(in-sync replica set)。 ISR在Leader中維護,也叫同步副本隊列,就是leader 與leader保持同步的followers的集合。 當ISR中的Follower完成數據的同步以後,Leader就會給Producer發送ACK,若是Follower未在規定的時間同步數據,則將其踢出ISR。當Leader掛掉的時候,在ISR中選舉出一個新的Leader。學習
在學習複製原理以前,先看兩個概念:HW(HighWatermark)和LEO(LogEndOffset):ui
如圖: 3d
Leader與Follower中,都會維護各自的HW,對於新消息的寫入,Consumer並不能當即被消費,須要等待ISR中的Followers從Leader中複製完成。 下圖說明了新消息寫入Partition後的數據複製過程: blog
由圖可知,Kafka的複製既不是同步也不是異步,其在可靠性和吞吐量上有很好的平衡。隊列
當Producer向Leader發送數據的時候,能夠經過Kafka提供的三種ACK應答機制,對數據的可靠性與延遲的要求作平衡。 經過配置request.required.acks實現。kafka
Producer不等待Broker的ACK,這能保證最低的延遲,可是當Broker故障時,數據可能丟失,便可靠性最低。 體現了At Most Once語義,最多一次,數據只會發送一次,不保證數據會丟失。同步
Producer等待Broker中partition的Leader落盤成功後返回ACK。若是在Follower同步結束以前Leader故障,數據會丟失。it
Producer等待Partition的Leader和Follower所有落盤成功後返回ACK。若是在數據同步完成後,發送ACK以前Leader故障,Producer會從新發送消息,形成數據重複。 這體現了At Least Once語義,至少一次,能夠保證數據不會丟失,可是不保證數據重複。
At Least Once 冪等性 = Exactly Once。 Kafka中冪等性是經過Broker初始化時分配的PID來保證。發往同一Partition的消息會附帶Sequence Number(SN),而Broker會對(PID,Partition,SN)作緩存,當相同主鍵的消息提交時,Broker只會持久化一條。 可是PID重啓後就會變化,不一樣的Partition也具備不一樣的主鍵,因此冪等性沒法保證跨分區會話的Exactly Once。
Follower故障後會被臨時踢出ISR,當Follower恢復後,Follower會讀取本地磁盤記錄的上次的HW,並將log文件高於HW的部分截取掉,從HW開始向Leader同步。等該Follower的LEO大於等於該partition的HW,即Follower追上Leader以後,就會被從新加入ISR。
Leader發生故障,會從ISR中選舉出一個新的Leader,其他的Follower會先將各自的log文件高於各自HW的部分截取掉,以後重新的Leader同步數據。
kafka會在Zookeeper中爲每一個partition動態的維護着ISR,當Leader掛掉後,會從ISR中順序選擇一個Follower做爲主。 若是碰巧ISR中Follower所有掛掉,那麼有兩種選擇:
怎麼選擇就要在可用性與一致性之間作權衡了。