您好,登錄后才能下訂單哦!
對于一個復雜的分布式系統,如果沒有豐富的經驗和牛逼的架構能力,很難把系統做得簡單易維護,我們都知道,一個軟件的生命周期中,后期維護占了70%,所以系統的可維護性是極其重要的, kafka 能成為大數據領域的事實標準,很大原因是因為運維起來很方便簡單,今天我們來看下 kafka 是怎么來簡化運維操作的。
歡迎學Java和大數據的朋友們加入java架構交流: 855835163
群內提供免費的架構資料還有:Java工程化、高性能及分布式、高性能、深入淺出。高架構。性能調優、Spring,MyBatis,Netty源碼分析和大數據等多個知識點高級進階干貨的免費直播講解 可以進來一起學習交流哦
kafka 使用多副本來保證消息不丟失,多副本就涉及到kafka的復制機制,在一個超大規模的集群中,時不時地這個點磁盤壞了,那個點cpu負載高了,出現各種各樣的問題,多個副本之間的復制,如果想完全自動化容錯,就要做一些考量和取舍了。我們舉個例子說明下運維中面對的復雜性,我們都知道 kafka 有個 ISR集合,我先說明下這個概念:
kafka不是完全同步,也不是完全異步,是一種ISR機制:
leader會維護一個與其基本保持同步的Replica列表,該列表稱為ISR(in-sync Replica),每個Partition都會有一個ISR,而且是由leader動態維護
如果一個follower比一個leader落后太多,或者超過一定時間未發起數據復制請求,則leader將其重ISR中移除
在這種機制下, 如果一個 producer 一個請求發送的消息條數太多,導致flower瞬間落后leader太多怎么辦?如果 follower不停的移入移出 ISR 會不會影響性能?如果對這種情況加了報警,就有可能造成告警轟炸,如果我們不加報警,如果是broker 掛掉或者 broker 因為IO性能或者GC問題夯住的情況導致落后leader太多,這種真正需要報警情況怎么辦呢? 今天我們來看下 kafka 是怎么在設計上讓我們完全避免這種運維中頭疼的問題的。
kafka的復制機制
kafka 每個分區都是由順序追加的不可變的消息序列組成,每條消息都一個唯一的offset 來標記位置。
kafka中的副本機制是以分區粒度進行復制的,我們在kafka中創建 topic的時候,都可以設置一個復制因子,這個復制因子決定著分區副本的個數,如果leader 掛掉了,kafka 會把分區主節點failover到其他副本節點,這樣就能保證這個分區的消息是可用的。leader節點負責接收producer 打過來的消息,其他副本節點(follower)從主節點上拷貝消息。
kakfa 日志復制算法提供的保證是當一條消息在 producer 端認為已經 committed的之后,如果leader 節點掛掉了,其他節點被選舉成為了 leader 節點后,這條消息同樣是可以被消費到的。
這樣的話,leader 選舉的時候,只能從 ISR集合中選舉,集合中的每個點都必須是和leader消息同步的,也就是沒有延遲,分區的leader 維護ISR 集合列表,如果某個點落后太多,就從 ISR集合中踢出去。 producer 發送一條消息到leader節點后, 只有當ISR中所有Replica都向Leader發送ACK確認這條消息時,leader才commit,這時候producer才能認為這條消息commit了,正是因為如此,kafka客戶端的寫性能取決于ISR集合中的最慢的一個broker的接收消息的性能,如果一個點性能太差,就必須盡快的識別出來,然后從ISR集合中踢出去,以免造成性能問題。
一個副本怎么才算是跟得上leader的副本
一個副本不能 “caught up” leader 節點,就有可能被從 ISR集合中踢出去,我們舉個例子來說明,什么才是真正的 “caught up” —— 跟leader節點消息同步。
kafka 中的一個單分區的 topic — foo,復制因子為 3 ,分區分布和 leader 和 follower 如下圖,現在broker 2和3 是 follower 而且都在 ISR 集合中。我們設置 replica.lag.max.messages 為4,只要 follower 只要不落后leader 大于3條消息,就然后是跟得上leader的節點,就不會被踢出去, 設置 replica.lag.time.max.ms 為 500ms, 意味著只要 follower 在每 500ms內發送fetch請求,就不會被認為已經dead ,不會從ISR集合中踢出去。
現在 producer 發送一條消息,offset 為3, 這時候 broker 3 發生了 GC, 入下圖:
因為 broker 3 現在在 ISR 集合中, 所以要么 broker 3 拉取同步上這條 offset 為3 的消息,要么 3 被從 ISR集合中踢出去,不然這條消息就不會 committed, 因為 replica.lag.max.messages=4 為4, broker 3 只落后一條消息,不會從ISR集合中踢出去, broker 3 如果這時候 GC 100ms, GC 結束,然后拉取到 offset 為3的消息,就再次跟 leader 保持完全同步,整個過程一直在 ISR集合中,如下圖:
什么時候一個副本才會從ISR集合中踢出去
一個副本被踢出 ISR集合的幾種原因:
一個副本在一段時間內都沒有跟得上 leader 節點,也就是跟leader節點的差距大于 replica.lag.max.messages , 通常情況是 IO性能跟不上,或者CPU 負載太高,導致 broker 在磁盤上追加消息的速度低于接收leader 消息的速度。
一個 broker 在很長時間內(大于 replica.lag.time.max.ms )都沒有向 leader 發送fetch 請求, 可能是因為 broker 發生了 full GC, 或者因為別的原因掛掉了。
一個新 的 broker 節點,比如同一個 broker id, 磁盤壞掉,新換了一臺機器,或者一個分區 reassign 到一個新的broker 節點上,都會從分區leader 上現存的最老的消息開始同步。
所以說 kafka 0.8 版本后設置了兩個參數 , replica.lag.max.messages 用來識別性能一直很慢的節點, replica.lag.time.max.ms 用來識別卡住的節點。
一個節點在什么情況下真正處于落后狀態
從上面的情況來看,兩個參數看似已經足夠了,如果一個副本超過 replica.lag.time.max.ms 還沒有發送fetch同步請求, 可以認為這個副本節點卡住了,然后踢出去,但是還有一種比較特殊的情況沒有考慮到,我們上文中設置 replica.lag.max.messages 為4,之所以設置為 4, 是我們已經知道 producer 每次請求打過來的消息數都在 4 以下,如果我們的參數是作用于多個 topic 的情況,那么這個 producer 最大打過來的消息數目就不好估計了,或者說在經常出現流量抖動的情況下,就會出現一個什么情況呢,我們還是使用例子說明:
如果我們的 topic — foo 的 producer 因為流量抖動打過來一個 包含 4條消息的請求,我們設置的 replica.lag.max.messages 還是為4, 這個時候,所有的 follower 都會因為超出落后條數被踢出 ISR集合:
然后,因為 follower 是正常的,所以下一次 fetch 請求就會又追上 leader, 這時候就會再次加入 ISR 集合,如果經常性的抖動,就會不斷的移入移出ISR集合,會造成令人頭疼的 告警轟炸。
這里的核心問題是,在海量的 topic 情況下,或者經常性的流量抖動情況下,我們不能對 topic 的producer 每次打過來的消息數目做任何假設,所以就不太好定出來一個 合適的 eplica.lag.max.messages 值
一個配置全部搞定
其實只有兩種情況是異常的,一種就是卡住,另外一種是follower 性能慢,如果我們只根據 follower 落后 leader 多少來判斷是否應該把 follower 提出ISR集合,就必須要對流量進行預測估計,怎么才能避免這種不靠譜的估計呢,kafka 給出 的方案是這樣的,對 replica.lag.time.max.ms 這個配置的含義做了增強,和之前一樣,如果 follower 卡住超過這個時間不發送fetch請求, 會被踢出ISR集合,新的增強邏輯是,在 follower 落后 leader 超過 eplica.lag.max.messages 條消息的時候,不會立馬踢出ISR 集合,而是持續落后超過 replica.lag.time.max.ms 時間,才會被踢出 ,這樣就能避免流量抖動造成的運維問題,因為follower 在下一次fetch的時候就會跟上leader, 這樣就也不用對 topic 的寫入速度做任何的估計嘍。
歡迎學Java和大數據的朋友們加入java架構交流: 855835163
群內提供免費的架構資料還有:Java工程化、高性能及分布式、高性能、深入淺出。高架構。性能調優、Spring,MyBatis,Netty源碼分析和大數據等多個知識點高級進階干貨的免費直播講解 可以進來一起學習交流哦
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。