掃二維碼與項(xiàng)目經(jīng)理溝通
我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
作者:莊秋濤 2017-08-30 16:47:49
分布式
Kafka Kafka是一種高吞吐量、分布式、基于發(fā)布/訂閱的消息系統(tǒng),最初由LinkedIn公司開發(fā),使用Scala語(yǔ)言編寫,目前是Apache的開源項(xiàng)目。

我們擁有10余年網(wǎng)頁(yè)設(shè)計(jì)和網(wǎng)站建設(shè)經(jīng)驗(yàn),從網(wǎng)站策劃到網(wǎng)站制作,我們的網(wǎng)頁(yè)設(shè)計(jì)師為您提供的解決方案。為企業(yè)提供成都網(wǎng)站建設(shè)、成都做網(wǎng)站、微信開發(fā)、小程序開發(fā)、移動(dòng)網(wǎng)站建設(shè)、HTML5、等業(yè)務(wù)。無(wú)論您有什么樣的網(wǎng)站設(shè)計(jì)或者設(shè)計(jì)方案要求,我們都將富于創(chuàng)造性的提供專業(yè)設(shè)計(jì)服務(wù)并滿足您的需求。
一、Kafka簡(jiǎn)介
Kafka是一種高吞吐量、分布式、基于發(fā)布/訂閱的消息系統(tǒng),最初由LinkedIn公司開發(fā),使用Scala語(yǔ)言編寫,目前是Apache的開源項(xiàng)目。
跟RabbitMQ、RocketMQ等目前流行的開源消息中間件相比,Kakfa具有高吞吐、低延遲等特點(diǎn),在大數(shù)據(jù)、日志收集等應(yīng)用場(chǎng)景下被廣泛使用。
本文主要簡(jiǎn)單介紹Kafka的設(shè)計(jì)原理。
二、Kafka架構(gòu)
基本概念:
三、Kafka設(shè)計(jì)原理
3.1 數(shù)據(jù)存儲(chǔ)設(shè)計(jì)
partition以文件形式存儲(chǔ)在文件系統(tǒng),目錄命名規(guī)則:
partition的數(shù)據(jù)文件
partition中的每條Message包含了以下三個(gè)屬性:
其中offset表示Message在這個(gè)partition中的偏移量,offset不是該Message在partition數(shù)據(jù)文件中的實(shí)際存儲(chǔ)位置,而是邏輯上一個(gè)值,它唯一確定了partition中的一條Message,可以認(rèn)為offset是partition中Message的id;MessageSize表示消息內(nèi)容data的大小;data為Message的具體內(nèi)容。
partition的數(shù)據(jù)文件由以上格式的Message組成,按offset由小到大排列在一起。
如果一個(gè)partition只有一個(gè)數(shù)據(jù)文件:
Kafka通過分段和索引來(lái)提高查找效率。
數(shù)據(jù)文件分段segment
partition物理上由多個(gè)segment文件組成,每個(gè)segment大小相等,順序讀寫。每個(gè)segment數(shù)據(jù)文件以該段中最小的offset命名,文件擴(kuò)展名為.log。這樣在查找指定offset的Message的時(shí)候,用二分查找就可以定位到該Message在哪個(gè)segment數(shù)據(jù)文件中。
數(shù)據(jù)文件索引
數(shù)據(jù)文件分段使得可以在一個(gè)較小的數(shù)據(jù)文件中查找對(duì)應(yīng)offset的Message了,但是這依然需要順序掃描才能找到對(duì)應(yīng)offset的Message。為了進(jìn)一步提高查找的效率,Kafka為每個(gè)分段后的數(shù)據(jù)文件建立了索引文件,文件名與數(shù)據(jù)文件的名字是一樣的,只是文件擴(kuò)展名為.index。
索引文件中包含若干個(gè)索引條目,每個(gè)條目表示數(shù)據(jù)文件中一條Message的索引。索引包含兩個(gè)部分,分別為相對(duì)offset和position。
index文件中并沒有為數(shù)據(jù)文件中的每條Message建立索引,而是采用了稀疏存儲(chǔ)的方式,每隔一定字節(jié)的數(shù)據(jù)建立一條索引。這樣避免了索引文件占用過多的空間,從而可以將索引文件保留在內(nèi)存中。但缺點(diǎn)是沒有建立索引的Message也不能一次定位到其在數(shù)據(jù)文件的位置,從而需要做一次順序掃描,但是這次順序掃描的范圍就很小了。
總結(jié)
查找某個(gè)offset的消息,先二分法找出消息所在的segment文件(因?yàn)槊總€(gè)segment的命名都是以該文件中消息offset最小的值命名);然后,加載對(duì)應(yīng)的.index索引文件到內(nèi)存,同樣二分法找出小于等于給定offset的***的那個(gè)offset記錄(相對(duì)offset,position);***,根據(jù)position到.log文件中,順序查找出offset等于給定offset值的消息。
由于消息在partition的segment數(shù)據(jù)文件中是順序讀寫的,且消息消費(fèi)后不會(huì)刪除(刪除策略是針對(duì)過期的segment文件),這種順序磁盤IO存儲(chǔ)設(shè)計(jì)是Kafka高性能很重要的原因。
3.2 生產(chǎn)者設(shè)計(jì)
3.3 消費(fèi)者設(shè)計(jì)
隊(duì)列模式
隊(duì)列模式,指每條消息只會(huì)有一個(gè)Consumer消費(fèi)到。Kafka保證同一Consumer Group中只有一個(gè)Consumer會(huì)消費(fèi)某條消息。
如果有partition或者Consumer的增減,為了保證均衡消費(fèi),需要實(shí)現(xiàn)Consumer Rebalance,分配算法如下:
broker對(duì)Consumer設(shè)計(jì)原理:
如圖,Last Commited Offset指Consumer最近一次提交的消費(fèi)記錄offset,Current Position是當(dāng)前消費(fèi)的位置,High Watermark是成功拷貝到log的所有副本節(jié)點(diǎn)(partition的所有ISR節(jié)點(diǎn),下文介紹)的最近消息的offset,Log End Offset是寫入log中***一條消息的offset+1。
從Consumer的角度來(lái)看,最多只能讀取到High watermark的位置,后面的消息對(duì)消費(fèi)者不可見,因?yàn)槲赐耆珡?fù)制的數(shù)據(jù)還沒可靠存儲(chǔ),有丟失可能。
發(fā)布訂閱模式
發(fā)布訂閱模式,又指廣播模式,Kafka保證topic的每條消息會(huì)被所有Consumer Group消費(fèi)到,而對(duì)于同一個(gè)Consumer Group,還是保證只有一個(gè)Consumer實(shí)例消費(fèi)到這條消息。
3.4 Replication設(shè)計(jì)
作為消息中間件,數(shù)據(jù)的可靠性以及系統(tǒng)的可用性,必然依賴數(shù)據(jù)副本的設(shè)計(jì)。
Kafka的replica副本單元是topic的partition,一個(gè)partition的replica數(shù)量不能超過broker的數(shù)量,因?yàn)橐粋€(gè)broker最多只會(huì)存儲(chǔ)這個(gè)partition的一個(gè)副本。所有消息生產(chǎn)、消費(fèi)請(qǐng)求都是由partition的leader replica來(lái)處理,其他follower replica負(fù)責(zé)從leader復(fù)制數(shù)據(jù)進(jìn)行備份。
Replica均勻分布到整個(gè)集群,Replica的算法如下:
如圖,TopicA有三個(gè)partition:part0、part1、part2,每個(gè)partition的replica數(shù)等于2(一個(gè)是leader,另一個(gè)是follower),按照以上算法會(huì)均勻落到三個(gè)broker上。
broker對(duì)replica管理:
選舉出一個(gè)broker作為controller,由它Watch Zookeeper,負(fù)責(zé)partition的replica的集群分配,以及l(fā)eader切換選舉等流程。
In-Sync-Replica(ISR)
分布式系統(tǒng)在處理節(jié)點(diǎn)故障時(shí),需要預(yù)先明確節(jié)點(diǎn)的”failure”和”alive”的定義。對(duì)于Kafka節(jié)點(diǎn),判斷是”alive”有以下兩個(gè)條件:
Kafka將滿足以上條件的replica節(jié)點(diǎn)認(rèn)為是”in sync”(同步中),稱為In-Sync-Replica(ISR)。
Kafka的Zookeeper維護(hù)了每個(gè)partition的ISR信息,理想情況下,ISR包含了partition的所有replica所在的broker節(jié)點(diǎn)信息,而當(dāng)某些節(jié)點(diǎn)不滿足以上條件時(shí),ISR可能只包含部分replica。例如,上圖中的TopicA-part0的ISR列表可能是[broker1,broker2,broker3],也可能是[broker1,broker3]和[broker1]。
數(shù)據(jù)可靠性
Kafka如何保證數(shù)據(jù)可靠性?首先看下,Producer生產(chǎn)一條消息,該消息被認(rèn)為是”committed”(即broker認(rèn)為消息已經(jīng)可靠存儲(chǔ))的過程:
ISR機(jī)制下的數(shù)據(jù)復(fù)制,既不是完全的同步復(fù)制,也不是單純的異步復(fù)制,這是Kafka高吞吐很重要的機(jī)制。同步復(fù)制要求所有能工作的follower都復(fù)制完,這條消息才會(huì)被認(rèn)為committed,這種復(fù)制方式極大的影響了吞吐量。而異步復(fù)制方式下,follower異步的從leader復(fù)制數(shù)據(jù),數(shù)據(jù)只要被leader寫入log就被認(rèn)為已經(jīng)committed,這種情況下如果follower都復(fù)制完都落后于leader,而如果leader突然宕機(jī),則會(huì)丟失數(shù)據(jù)。而Kafka的這種使用ISR的方式則很好的均衡了確保數(shù)據(jù)不丟失以及吞吐量,follower可以批量的從leader復(fù)制數(shù)據(jù),數(shù)據(jù)復(fù)制到內(nèi)存即返回ack,這樣極大的提高復(fù)制性能,當(dāng)然數(shù)據(jù)仍然是有丟失風(fēng)險(xiǎn)的。
Kafka本身定位于高性能的MQ,更多注重消息吞吐量,在此基礎(chǔ)上結(jié)合ISR的機(jī)制去盡量保證消息的可靠性,但不是絕對(duì)可靠的。
服務(wù)可用性
Kafka所有收發(fā)消息請(qǐng)求都由leader節(jié)點(diǎn)處理,由以上數(shù)據(jù)可靠性設(shè)計(jì)可知,當(dāng)ISR的follower replica故障后,leader會(huì)及時(shí)地從ISR列表中把它剔除掉,并不影響服務(wù)可用性,那么當(dāng)leader故障后會(huì)怎樣呢?如何選舉新的leader?
leader選舉
因此,可以看出,只要ISR中至少有一個(gè)replica,Kafka就能保證服務(wù)的可用性(但不保證網(wǎng)絡(luò)分區(qū)下的可用性)。
容災(zāi)和數(shù)據(jù)一致性
分布式系統(tǒng)的容災(zāi)能力,跟其本身針對(duì)數(shù)據(jù)一致性考慮所選擇的算法有關(guān),例如,Zookeeper的Zab算法,raft算法等。Kafka的ISR機(jī)制和這些Majority Vote算法對(duì)比如下:
ISR機(jī)制能容忍更多的節(jié)點(diǎn)失敗。假如replica節(jié)點(diǎn)有2f+1個(gè),每個(gè)partition最多能容忍2f個(gè)失敗,且不丟失消息數(shù)據(jù);但相對(duì)Majority Vote選舉算法,只能最多容忍f個(gè)失敗。
在消息committed持久化上,ISR需要等2f個(gè)節(jié)點(diǎn)返回ack,但Majority Vote只需等f(wàn)+1個(gè)節(jié)點(diǎn)返回ack,且不依賴處理最慢的follower節(jié)點(diǎn),因此Majority Vote有優(yōu)勢(shì)
ISR機(jī)制能節(jié)省更多replica節(jié)點(diǎn)數(shù)。例如,要保證f個(gè)節(jié)點(diǎn)可用,ISR方式至少要f個(gè)節(jié)點(diǎn),而Majority Vote至少需要2f+1個(gè)節(jié)點(diǎn)。
如果所有replica都宕機(jī)了,有兩種方式恢復(fù)服務(wù):
***種方式消息不會(huì)丟失(只能說這種方式最有可能不丟而已),第二種方式可能會(huì)丟消息,但能盡快恢復(fù)服務(wù)可用。這是可用性和一致性場(chǎng)景的兩種考慮,Kafka默認(rèn)選擇第二種,用戶也可以自主配置。
大部分考慮CP的分布式系統(tǒng)(假設(shè)2f+1個(gè)節(jié)點(diǎn)),為了保證數(shù)據(jù)一致性,最多只能容忍f個(gè)節(jié)點(diǎn)的失敗,而Kafka為了兼顧可用性,允許最多2f個(gè)節(jié)點(diǎn)失敗,因此是無(wú)法保證數(shù)據(jù)強(qiáng)一致的。
如圖所示,一開始ISR數(shù)量等于3,正常同步數(shù)據(jù),紅色部分開始,leader發(fā)現(xiàn)其他兩個(gè)follower復(fù)制進(jìn)度太慢或者其他原因(網(wǎng)絡(luò)分區(qū)、節(jié)點(diǎn)故障等),將其從ISR剔除后,leader單節(jié)點(diǎn)存儲(chǔ)數(shù)據(jù);然后,leader宕機(jī),觸發(fā)重新選舉第二節(jié)點(diǎn)為leader,重新開始同步數(shù)據(jù),但紅色部分的數(shù)據(jù)在新leader上是沒有的;***原leader節(jié)點(diǎn)恢復(fù)服務(wù)后,重新從新leader上復(fù)制數(shù)據(jù),而紅色部分的數(shù)據(jù)已經(jīng)消費(fèi)不到了。
因此,為了減少數(shù)據(jù)丟失的概率,可以設(shè)置Kafka的ISR最小replica數(shù),低于該值后直接返回不可用,當(dāng)然是以犧牲一定可用性和吞吐量為前提了。
重復(fù)消息
消息傳輸有三種方式:
At most once:消息可能會(huì)丟失,但不會(huì)重復(fù)傳輸
At least once:消息不會(huì)丟失,但可能重復(fù)傳輸
Exactly once:消息保證會(huì)被傳輸一次且僅傳輸一次
Kafka實(shí)現(xiàn)了第二種方式,即,可能存在重復(fù)消息,需要業(yè)務(wù)自己保證消息冪等性處理。
3.5 高吞吐設(shè)計(jì)
這是用戶在消息吞吐量和持久化之間做的權(quán)衡選擇,持久化等級(jí)越高,生產(chǎn)消息吞吐量越小,反之,持久化等級(jí)越低,吞吐量越高。
3.6 HA基本原理
broker HA
broker集群信息由Zookeeper維護(hù),并選舉出一個(gè)controller。所有partition的leader選舉都由controller決定,將leader的變更直接通過rpc方式通知需要為此做出響應(yīng)的brokers;controller也負(fù)責(zé)增刪topic以及partition replica的重新分配。
controller在Zookeeper上注冊(cè)watch,一旦有broker宕機(jī),其對(duì)應(yīng)在Zookeeper的臨時(shí)節(jié)點(diǎn)自動(dòng)被刪除,controller對(duì)宕機(jī)broker上的所有partition重新分配新leader;如果controller宕機(jī),其他broker通過Zookeeper選舉出新的controller,然后同樣對(duì)宕機(jī)broker上的所有partition重新分配新leader。
partition HA
partition leader所在的broker宕機(jī),如上所述,broker controller根據(jù)動(dòng)態(tài)維護(hù)的ISR,會(huì)重新在剩下的broker機(jī)器中選出ISR里面的一個(gè)成員成為新的leader。如果ISR中至少有一個(gè)follower,則可以確保已經(jīng)committed的數(shù)據(jù)不丟失;否則選擇任意一個(gè)replica作為leader,該場(chǎng)景可能會(huì)有潛在的數(shù)據(jù)丟失;如果partition所有的replica都宕機(jī)了,就無(wú)法保證數(shù)據(jù)不丟失了,有兩種恢復(fù)方案,上文已介紹過。
四、推廣
騰訊云即將推出高性能的消息隊(duì)列服務(wù)Ckafka,完全兼容開源Kafka API(0.9版本)。Ckafka服務(wù)端完全托管在騰訊云上,用戶無(wú)需自己維護(hù)和搭建,使用開源Kafka API客戶端即可訪問實(shí)例,大大降低了用戶使用Kafka的門檻,歡迎體驗(yàn):)
原文鏈接:https://cloud.tencent.com/community/article/369570
【本文是51CTO專欄作者“騰訊云技術(shù)社區(qū)”的原創(chuàng)稿件,轉(zhuǎn)載請(qǐng)通過51CTO聯(lián)系原作者獲取授權(quán)】

我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流