kafka 組成 原理 詳解 架構(gòu)

數(shù)據(jù)正確性保證
日志功能里有一個(gè)配置參數(shù)M,可對(duì)在強(qiáng)制進(jìn)行磁盤(pán)刷新之前可寫(xiě)入的消息的最大條目數(shù)進(jìn)行控制。在系統(tǒng)啟動(dòng)時(shí)會(huì)運(yùn)行一個(gè)日志恢復(fù)過(guò)程,對(duì)最新的日志段內(nèi)所有消息進(jìn)行迭代,以對(duì)每條消息項(xiàng)的有效性進(jìn)行驗(yàn)證。一條消息項(xiàng)是合法的,僅當(dāng)其大小加偏移量小于文件的大小并且該消息中有效載荷的CRC32值同該消息中存儲(chǔ)的CRC值相等。在探測(cè)出有數(shù)據(jù)損壞的情況下,就要將文件按照最后一個(gè)有效的偏移量進(jìn)行截?cái)唷?/p>

要注意,這里有兩種必需處理的數(shù)據(jù)損壞情況:由于系統(tǒng)崩潰造成的未被正常寫(xiě)入的數(shù)據(jù)塊(block)因而需要截?cái)嗟那闆r以及由于文件中被加入了毫無(wú)意義的數(shù)據(jù)塊而造成的數(shù)據(jù)損壞情況。造成數(shù)據(jù)損壞的原因是,一般來(lái)說(shuō)OS并不能保證文件索引節(jié)點(diǎn)(inode)和實(shí)際數(shù)據(jù)塊這兩者的寫(xiě)入順序,因此,除了可能會(huì)丟失未刷新的已寫(xiě)入數(shù)據(jù)之外,在索引節(jié)點(diǎn)已經(jīng)用新的文件大小更新了但在將數(shù)據(jù)塊寫(xiě)入磁盤(pán)塊之前發(fā)生了系統(tǒng)崩潰的情況下,文件就可能會(huì)獲得一些毫無(wú)意義的數(shù)據(jù)。CRC值就是用于這種極端情況,避免由此造成整個(gè)日志文件的損壞(盡管未得到保存的消息當(dāng)然是真的找不回來(lái)了)。

分發(fā)
Zookeeper目錄
接下來(lái)討論zookeeper用于在使用者和代理直接進(jìn)行協(xié)調(diào)的結(jié)構(gòu)和算法。

記法
當(dāng)一個(gè)路徑中的元素是用[xyz]這種形式表示的時(shí),其意思是, xyz的值并不固定而且實(shí)際上x(chóng)yz的每種可能的值都有一個(gè)zookpeer z節(jié)點(diǎn)(znode)。例如,/topics/[topic]表示了一個(gè)名為/topics的目錄,其中包含的子目錄同話題對(duì)應(yīng),一個(gè)話題一個(gè)目錄并且目錄名即為話題的名稱(chēng)。也可以給出數(shù)字范圍,例如[0...5],表示的是子目錄0、1、2、3、4。箭頭->用于給出z節(jié)點(diǎn)的內(nèi)容。例如/hello -> world表示的是一個(gè)名稱(chēng)為/hello的z節(jié)點(diǎn),包含的值為"world"。

代理節(jié)點(diǎn)的注冊(cè)
/brokers/ids/[0...N] --> host:port (ephemeral node)
上面是所有出現(xiàn)的代理節(jié)點(diǎn)的列表,列表中每一項(xiàng)都提供了一個(gè)具有唯一性的邏輯代理id,用于讓使用者能夠識(shí)別代理的身份(這個(gè)必須在配置中給出)。在啟動(dòng)時(shí),代理節(jié)點(diǎn)就要用/brokers/ids下列出的邏輯代理id創(chuàng)建一個(gè)z節(jié)點(diǎn),并在自己注冊(cè)到系統(tǒng)中。使用邏輯代理id的目的是,可以讓我們?cè)诓挥绊憯?shù)據(jù)使用者的情況下就能把一個(gè)代理搬到另一臺(tái)不同的物理機(jī)器上。試圖用已在使用中的代理id(比如說(shuō),兩個(gè)服務(wù)器配置成了同一個(gè)代理id)進(jìn)行注冊(cè)會(huì)導(dǎo)致發(fā)生錯(cuò)誤。

因?yàn)榇硎且苑情L(zhǎng)久性z節(jié)點(diǎn)的方式注冊(cè)的,所以這個(gè)注冊(cè)過(guò)程是動(dòng)態(tài)的,當(dāng)代理關(guān)閉或宕機(jī)后注冊(cè)信息就會(huì)消失(至此要數(shù)據(jù)使用者,該代理不再有效)。

代理話題的注冊(cè)
/brokers/topics/[topic]/[0...N] --> nPartions (ephemeral node)
每個(gè)代理會(huì)都要注冊(cè)在某話題之下,注冊(cè)后它會(huì)維護(hù)并保存該話題的分區(qū)總數(shù)。

使用者和使用者小組
為了對(duì)數(shù)據(jù)的使用進(jìn)行負(fù)載均衡并記錄使用者使用的每個(gè)代理上的每個(gè)分區(qū)上的偏移量,所有話題的使用者都要在Zookeeper中進(jìn)行注冊(cè)。

多個(gè)使用者可以組成一個(gè)小組共同使用一個(gè)單個(gè)的話題。同一小組內(nèi)的每個(gè)使用者共享同一個(gè)給定的group_id。比如說(shuō),如果某個(gè)使用者負(fù)責(zé)用三臺(tái)機(jī)器進(jìn)行某某處理過(guò)程,你就可以為這組使用者分配一個(gè)叫做“某某”的id。這個(gè)小組id是在使用者的配置文件中指定的,并且這就是你告訴使用者它到底屬于哪個(gè)組的方法。

小組內(nèi)的使用者要盡量公正地劃分出分區(qū),每個(gè)分區(qū)僅為小組內(nèi)的一個(gè)使用者所使用。

使用者ID的注冊(cè)
除了小組內(nèi)的所有使用者都要共享一個(gè)group_id之外,每個(gè)使用者為了要同其它使用者區(qū)別開(kāi)來(lái),還要有一個(gè)非永久性的、具有唯一性的consumer_id(采用hostname:uuid的形式)。 consumer_id要在以下的目錄中進(jìn)行注冊(cè)。

/consumers/[group_id]/ids/[consumer_id] --> {"topic1": #streams, ..., "topicN": #streams} (ephemeral node)
小組內(nèi)的每個(gè)使用者都要在它所屬的小組中進(jìn)行注冊(cè)并采用consumer_id創(chuàng)建一個(gè)z節(jié)點(diǎn)。z節(jié)點(diǎn)的值包含了一個(gè)的map。 consumer_id只是用來(lái)識(shí)別小組內(nèi)活躍的每個(gè)使用者。使用者建立的z節(jié)點(diǎn)是個(gè)臨時(shí)性的節(jié)點(diǎn),因此如果這個(gè)使用者進(jìn)程終止了,注冊(cè)信息也將隨之消失。

數(shù)據(jù)使用者偏移追蹤
數(shù)據(jù)使用者跟蹤他們?cè)诿總€(gè)分區(qū)中耗用的最大偏移量。這個(gè)值被存儲(chǔ)在一個(gè)Zookeeper(分布式協(xié)調(diào)系統(tǒng))目錄中。

/consumers/[group_id]/offsets/[topic]/[broker_id-partition_id] --> offset_counter_value ((persistent node)
分區(qū)擁有者注冊(cè)表
每個(gè)代理分區(qū)都被分配給了指定使用者小組中的單個(gè)數(shù)據(jù)使用者。數(shù)據(jù)使用者必須在耗用給定分區(qū)前確立對(duì)其的所有權(quán)。要確立其所有權(quán),數(shù)據(jù)使用者需要將其 id 寫(xiě)入到特定代理分區(qū)中的一個(gè)臨時(shí)節(jié)點(diǎn)(ephemeral node)中。

/consumers/[group_id]/owners/[topic]/[broker_id-partition_id] --> consumer_node_id (ephemeral node)

代理節(jié)點(diǎn)的注冊(cè)
代理節(jié)點(diǎn)之間基本上都是相互獨(dú)立的,因此它們只需要發(fā)布它們擁有的信息。當(dāng)有新的代理加入進(jìn)來(lái)時(shí),它會(huì)將自己注冊(cè)到代理節(jié)點(diǎn)注冊(cè)目錄中,寫(xiě)下它的主機(jī)名和端口。代理還要將已有話題的列表和它們的邏輯分區(qū)注冊(cè)到代理話題注冊(cè)表中。在代理上生成新話題時(shí),需要?jiǎng)討B(tài)的對(duì)話題進(jìn)行注冊(cè)。

使用者注冊(cè)算法
當(dāng)使用者啟動(dòng)時(shí),它要做以下這些事情:

將自己注冊(cè)到它屬小組下的使用者id注冊(cè)表。
注冊(cè)一個(gè)監(jiān)視使用者id列的表變化情況(有新的使用者加入或者任何現(xiàn)有使用者的離開(kāi))的變化監(jiān)視器。(每個(gè)變化都會(huì)觸發(fā)一次對(duì)發(fā)生變化的使用者所屬的小組內(nèi)的所有使用者進(jìn)行負(fù)載均衡。)
主次一個(gè)監(jiān)視代理id注冊(cè)表的變化情況(有新的代理加入或者任何現(xiàn)有的代理的離開(kāi))的變化監(jiān)視器。(每個(gè)變化都會(huì)觸發(fā)一次對(duì)所有小組內(nèi)的所有使用者負(fù)載均衡。)
如果使用者使用某話題過(guò)濾器創(chuàng)建了一個(gè)消息流,它還要注冊(cè)一個(gè)監(jiān)視代理話題變化情況(添加了新話題)的變化監(jiān)視器。(每個(gè)變化都會(huì)觸發(fā)一次對(duì)所有可用話題的評(píng)估,以找出話題過(guò)濾器過(guò)濾出哪些話題。新過(guò)濾出來(lái)的話題將觸發(fā)一次對(duì)該使用者所在的小組內(nèi)所有的使用者負(fù)載均衡。)
迫使自己在小組內(nèi)進(jìn)行重新負(fù)載均衡。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容