• 當前位置:聯(lián)升科技 > 技術(shù)資訊 > 行業(yè)動(dòng)態(tài) >

    因為一次 Kafka 宕機,我明白了 Kafka 高可用原理!

    2020-12-26    作者:JanusWoo    來(lái)源:掘金    閱讀: 次
    Kafka宕機引發(fā)的高可用問(wèn)題
    問(wèn)題要從一次Kafka的宕機開(kāi)始說(shuō)起。
    筆者所在的是一家金融科技公司,但公司內部并沒(méi)有采用在金融支付領(lǐng)域更為流行的RabbitMQ,而是采用了設計之初就為日志處理而生的Kafka,所以我一直很好奇Kafka的高可用實(shí)現和保障。從Kafka部署后,系統內部使用的Kafka一直運行穩定,沒(méi)有出現不可用的情況。
    但最近系統測試人員常反饋偶有Kafka消費者收不到消息的情況,登陸管理界面發(fā)現三個(gè)節點(diǎn)中有一個(gè)節點(diǎn)宕機掛掉了。但是按照高可用的理念,三個(gè)節點(diǎn)還有兩個(gè)節點(diǎn)可用怎么就引起了整個(gè)集群的消費者都接收不到消息呢?
    要解決這個(gè)問(wèn)題,就要從Kafka的高可用實(shí)現開(kāi)始講起。
    Kafka的多副本冗余設計
    不管是傳統的基于關(guān)系型數據庫設計的系統,還是分布式的如zookeeper、redis、Kafka、HDFS等等,實(shí)現高可用的辦法通常是采用冗余設計,通過(guò)冗余來(lái)解決節點(diǎn)宕機不可用問(wèn)題。
    首先簡(jiǎn)單了解Kafka的幾個(gè)概念:
    物理模型

    邏輯模型
    Broker(節點(diǎn)):Kafka服務(wù)節點(diǎn),簡(jiǎn)單來(lái)說(shuō)一個(gè)Broker就是一臺Kafka服務(wù)器,一個(gè)物理節點(diǎn)。
    Topic(主題):在Kafka中消息以主題為單位進(jìn)行歸類(lèi),每個(gè)主題都有一個(gè)Topic Name,生產(chǎn)者根據Topic Name將消息發(fā)送到特定的Topic,消費者則同樣根據Topic Name從對應的Topic進(jìn)行消費。
    Partition(分區):Topic(主題)是消息歸類(lèi)的一個(gè)單位,但每一個(gè)主題還能再細分為一個(gè)或多個(gè)Partition(分區),一個(gè)分區只能屬于一個(gè)主題。主題和分區都是邏輯上的概念,舉個(gè)例子,消息1和消息2都發(fā)送到主題1,它們可能進(jìn)入同一個(gè)分區也可能進(jìn)入不同的分區(所以同一個(gè)主題下的不同分區包含的消息是不同的),之后便會(huì )發(fā)送到分區對應的Broker節點(diǎn)上。
    Offset(偏移量):分區可以看作是一個(gè)只進(jìn)不出的隊列(Kafka只保證一個(gè)分區內的消息是有序的),消息會(huì )往這個(gè)隊列的尾部追加,每個(gè)消息進(jìn)入分區后都會(huì )有一個(gè)偏移量,標識該消息在該分區中的位置,消費者要消費該消息就是通過(guò)偏移量來(lái)識別。
    其實(shí),根據上述的幾個(gè)概念,是不是也多少猜到了Kafka的多副本冗余設計實(shí)現了?別急,咱繼續往下看。
    在Kafka 0.8版本以前,是沒(méi)有多副本冗余機制的,一旦一個(gè)節點(diǎn)掛掉,那么這個(gè)節點(diǎn)上的所有Partition的數據就無(wú)法再被消費。這就等于發(fā)送到Topic的有一部分數據丟失了。
    在0.8版本后引入副本記者則很好地解決宕機后數據丟失的問(wèn)題。副本是以Topic中每個(gè)Partition的數據為單位,每個(gè)Partition的數據會(huì )同步到其他物理節點(diǎn)上,形成多個(gè)副本。
    每個(gè)Partition的副本都包括一個(gè)Leader副本和多個(gè)Follower副本,Leader由所有的副本共同選舉得出,其他副本則都為Follower副本。在生產(chǎn)者寫(xiě)或者消費者讀的時(shí)候,都只會(huì )與Leader打交道,在寫(xiě)入數據后Follower就會(huì )來(lái)拉取數據進(jìn)行數據同步。

    就這么簡(jiǎn)單?是的,基于上面這張多副本架構圖就實(shí)現了Kafka的高可用。當某個(gè)Broker掛掉了,甭?lián)?,這個(gè)Broker上的Partition在其他Broker節點(diǎn)上還有副本。你說(shuō)如果掛掉的是Leader怎么辦?那就在Follower中在選舉出一個(gè)Leader即可,生產(chǎn)者和消費者又可以和新的Leader愉快地玩耍了,這就是高可用。
    你可能還有疑問(wèn),那要多少個(gè)副本才算夠用?Follower和Leader之間沒(méi)有完全同步怎么辦?一個(gè)節點(diǎn)宕機后Leader的選舉規則是什么?
    直接拋結論:
    多少個(gè)副本才算夠用? 副本肯定越多越能保證Kafka的高可用,但越多的副本意味著(zhù)網(wǎng)絡(luò )、磁盤(pán)資源的消耗更多,性能會(huì )有所下降,通常來(lái)說(shuō)副本數為3即可保證高可用,極端情況下將replication-factor參數調大即可。
    Follower和Lead之間沒(méi)有完全同步怎么辦? Follower和Leader之間并不是完全同步,但也不是完全異步,而是采用一種ISR機制(In-Sync Replica)。每個(gè)Leader會(huì )動(dòng)態(tài)維護一個(gè)ISR列表,該列表里存儲的是和Leader基本同步的Follower。如果有Follower由于網(wǎng)絡(luò )、GC等原因而沒(méi)有向Leader發(fā)起拉取數據請求,此時(shí)Follower相對于Leader是不同步的,則會(huì )被踢出ISR列表。所以說(shuō),ISR列表中的Follower都是跟得上Leader的副本。
    一個(gè)節點(diǎn)宕機后Leader的選舉規則是什么? 分布式相關(guān)的選舉規則有很多,像Zookeeper的Zab、Raft、Viewstamped Replication、微軟的PacificA等。而Kafka的Leader選舉思路很簡(jiǎn)單,基于我們上述提到的ISR列表,當宕機后會(huì )從所有副本中順序查找,如果查找到的副本在ISR列表中,則當選為L(cháng)eader。另外還要保證前任Leader已經(jīng)是退位狀態(tài)了,否則會(huì )出現腦裂情況(有兩個(gè)Leader)。怎么保證?Kafka通過(guò)設置了一個(gè)controller來(lái)保證只有一個(gè)Leader。
    Ack參數決定了可靠程度
    另外,這里補充一個(gè)面試考Kafka高可用必備知識點(diǎn):request.required.asks參數。
    Asks這個(gè)參數是生產(chǎn)者客戶(hù)端的重要配置,發(fā)送消息的時(shí)候就可設置這個(gè)參數。該參數有三個(gè)值可配置:0、1、All。
    第一種是設為0,意思是生產(chǎn)者把消息發(fā)送出去之后,之后這消息是死是活咱就不管了,有那么點(diǎn)發(fā)后即忘的意思,說(shuō)出去的話(huà)就不負責了。不負責自然這消息就有可能丟失,那就把可用性也丟失了。
    第二種是設為1,意思是生產(chǎn)者把消息發(fā)送出去之后,這消息只要順利傳達給了Leader,其他Follower有沒(méi)有同步就無(wú)所謂了。存在一種情況,Leader剛收到了消息,Follower還沒(méi)來(lái)得及同步Broker就宕機了,但生產(chǎn)者已經(jīng)認為消息發(fā)送成功了,那么此時(shí)消息就丟失了。注意,設為1是Kafka的默認配置!可見(jiàn)Kafka的默認配置也不是那么高可用,而是對高可用和高吞吐量做了權衡折中。
    第三種是設為All(或者-1),意思是生產(chǎn)者把消息發(fā)送出去之后,不僅Leader要接收到,ISR列表中的Follower也要同步到,生產(chǎn)者才會(huì )任務(wù)消息發(fā)送成功。
    進(jìn)一步思考,Asks=All就不會(huì )出現丟失消息的情況嗎?答案是否。當ISR列表只剩Leader的情況下,Asks=All相當于A(yíng)sks=1,這種情況下如果節點(diǎn)宕機了,還能保證數據不丟失嗎?因此只有在A(yíng)sks=All并且有ISR中有兩個(gè)副本的情況下才能保證數據不丟失。
    解決問(wèn)題
    繞了一大圈,了解了Kafka的高可用機制,終于回到我們一開(kāi)始的問(wèn)題本身,Kafka的一個(gè)節點(diǎn)宕機后為什么不可用?
    我在開(kāi)發(fā)測試環(huán)境配置的Broker節點(diǎn)數是3,Topic是副本數為3,Partition數為6,Asks參數為1。
    當三個(gè)節點(diǎn)中某個(gè)節點(diǎn)宕機后,集群首先會(huì )怎么做?沒(méi)錯,正如我們上面所說(shuō)的,集群發(fā)現有Partition的Leader失效了,這個(gè)時(shí)候就要從ISR列表中重新選舉Leader。如果ISR列表為空是不是就不可用了?并不會(huì ),而是從Partition存活的副本中選擇一個(gè)作為L(cháng)eader,不過(guò)這就有潛在的數據丟失的隱患了。
    所以,只要將Topic副本個(gè)數設置為和Broker個(gè)數一樣,Kafka的多副本冗余設計是可以保證高可用的,不會(huì )出現一宕機就不可用的情況(不過(guò)需要注意的是Kafka有一個(gè)保護策略,當一半以上的節點(diǎn)不可用時(shí)Kafka就會(huì )停止)。那仔細一想,Kafka上是不是有副本個(gè)數為1的Topic?
    問(wèn)題出在了__consumer_offset上,__consumer_offset是一個(gè)Kafka自動(dòng)創(chuàng )建的Topic,用來(lái)存儲消費者消費的offset(偏移量)信息,默認Partition數為50。而就是這個(gè)Topic,它的默認副本數為1。如果所有的Partition都存在于同一臺機器上,那就是很明顯的單點(diǎn)故障了!當將存儲__consumer_offset的Partition的Broker給Kill后,會(huì )發(fā)現所有的消費者都停止消費了。
    這個(gè)問(wèn)題怎么解決?
    第一點(diǎn),需要將__consumer_offset刪除,注意這個(gè)Topic時(shí)Kafka內置的Topic,無(wú)法用命令刪除,我是通過(guò)將logs刪了來(lái)實(shí)現刪除。
    第二點(diǎn),需要通過(guò)設置offsets.topic.replication.factor為3來(lái)將__consumer_offset的副本數改為3。
    通過(guò)將__consumer_offset也做副本冗余后來(lái)解決某個(gè)節點(diǎn)宕機后消費者的消費問(wèn)題。
    最后,關(guān)于為什么__consumer_offset的Partition會(huì )出現只存儲在一個(gè)Broker上而不是分布在各個(gè)Broker上感到困惑,如果有朋友了解的煩請指教~


    相關(guān)文章

    我們很樂(lè )意傾聽(tīng)您的聲音!
    即刻與我們取得聯(lián)絡(luò )
    成為日后肩并肩合作的伙伴。

    行業(yè)資訊

    聯(lián)系我們

    13387904606

    地址:新余市仙女湖區仙女湖大道萬(wàn)商紅A2棟

    手機:13755589003
    QQ:122322500
    微信號:13755589003

    江西新余網(wǎng)站設計_小程序制作_OA系統開(kāi)發(fā)_企業(yè)ERP管理系統_app開(kāi)發(fā)-新余聯(lián)升網(wǎng)絡(luò )科技有限公司 贛ICP備19013599號-1   贛公網(wǎng)安備 36050202000267號   

    微信二維碼
    色噜噜狠狠一区二区三区果冻|欧美亚洲日本国产一区|国产精品无码在线观看|午夜视频在线观看一区|日韩少妇一区二区无码|伊人亚洲日韩欧美一区二区|国产在线码观看清码视频