(此文轉(zhuǎn)載自樂(lè)字節(jié))
ZooKeeper 的作用
ZooKeeper 是一個(gè)開(kāi)源的分布式協(xié)調(diào)服務(wù)框架弥鹦,你也可以認(rèn)為它是一個(gè)可以保證一致性的分布式(小量)存儲(chǔ)系統(tǒng)。特別適合存儲(chǔ)一些公共的配置信息寒跳、集群的一些元數(shù)據(jù)等等聘萨。
它有持久節(jié)點(diǎn)和臨時(shí)節(jié)點(diǎn),而臨時(shí)節(jié)點(diǎn)這個(gè)玩意再配合 Watcher 機(jī)制就很有用童太。
當(dāng)創(chuàng)建臨時(shí)節(jié)點(diǎn)的客戶端與 ZooKeeper 斷連之后米辐,這個(gè)臨時(shí)節(jié)點(diǎn)就會(huì)消失,并且訂閱了節(jié)點(diǎn)狀態(tài)變更的客戶端會(huì)收到這個(gè)節(jié)點(diǎn)狀態(tài)變更的通知书释。
所以集群中某一服務(wù)上線或者下線翘贮,都可以被檢測(cè)到。因此可以用來(lái)實(shí)現(xiàn)服務(wù)發(fā)現(xiàn)爆惧,也可以實(shí)現(xiàn)故障轉(zhuǎn)移的監(jiān)聽(tīng)機(jī)制狸页。
Kafka 就是強(qiáng)依賴于 ZooKeeper,沒(méi)有 ZooKeeper 的話 Kafka 都無(wú)法運(yùn)行扯再。ZooKeeper 為 Kafka 提供了元數(shù)據(jù)的管理芍耘,例如一些 Broker 的信息、主題數(shù)據(jù)熄阻、分區(qū)數(shù)據(jù)等等斋竞。
在每個(gè) Broker 啟動(dòng)的時(shí)候,都會(huì)和 ZooKeeper 進(jìn)行交互饺律,這樣 ZooKeeper 就存儲(chǔ)了集群中所有的主題窃页、配置、副本等信息复濒。
還有一些選舉脖卖、擴(kuò)容等機(jī)制也都依賴 ZooKeeper 。
例如控制器的選舉:每個(gè) Broker 啟動(dòng)都會(huì)嘗試在 ZooKeeper 注冊(cè)/controller臨時(shí)節(jié)點(diǎn)來(lái)競(jìng)選控制器巧颈,第一個(gè)創(chuàng)建/controller節(jié)點(diǎn)的 Broker 會(huì)被指定為控制器畦木。
競(jìng)爭(zhēng)失敗的節(jié)點(diǎn)也會(huì)依賴 watcher 機(jī)制,監(jiān)聽(tīng)這個(gè)節(jié)點(diǎn)砸泛,如果控制器宕機(jī)了十籍,那么其它 Broker 會(huì)繼續(xù)來(lái)爭(zhēng)搶蛆封,實(shí)現(xiàn)控制器的 failover。
從上面就可以得知 ZooKeeper 對(duì) Kafka 來(lái)說(shuō)很重要勾栗。
那為什么要拋棄 ZooKeeper
軟件架構(gòu)都是演進(jìn)的惨篱,之所以要變更那肯定是因?yàn)槌霈F(xiàn)了瓶頸。
先來(lái)看看運(yùn)維的層面的問(wèn)題围俘。
首先身為一個(gè)中間件砸讳,需要依賴另一個(gè)中間件,這就感覺(jué)有點(diǎn)奇怪界牡。
你要說(shuō)依賴 Netty 這種簿寂,那肯定是沒(méi)問(wèn)題的。但是 Kafka 的運(yùn)行需要提供 ZooKeeper 集群宿亡,這其實(shí)有點(diǎn)怪怪的常遂。
就等于如果你公司要上 Kafka 就得跟著上 ZooKeeper ,被動(dòng)了增加了運(yùn)維的復(fù)雜度挽荠。
好比你去商場(chǎng)買衣服克胳,要買個(gè)上衣,服務(wù)員說(shuō)不單賣坤按,要買就得買一套毯欣,這錢是不是多花了?
所以運(yùn)維人員不僅得照顧 Kafka 集群臭脓,還得照顧 ZooKeeper 集群酗钞。
再看性能層面的問(wèn)題。
ZooKeeper 有個(gè)特點(diǎn)来累,強(qiáng)一致性砚作。
如果 ZooKeeper 集群的某個(gè)節(jié)點(diǎn)的數(shù)據(jù)發(fā)生變更,則會(huì)通知其它 ZooKeeper 節(jié)點(diǎn)同時(shí)執(zhí)行更新嘹锁,就得等著大家(超過(guò)半數(shù))都寫完了才行葫录,這寫入的性能就比較差了。
然后看到上面我說(shuō)的小量存儲(chǔ)系統(tǒng)了吧领猾,一般而言米同,ZooKeeper 只適用于存儲(chǔ)一些簡(jiǎn)單的配置或者是集群的元數(shù)據(jù),不是真正意義上的存儲(chǔ)系統(tǒng)摔竿。
如果寫入的數(shù)據(jù)量過(guò)大面粮,ZooKeeper 的性能和穩(wěn)定性就會(huì)下降,可能導(dǎo)致 Watch 的延時(shí)或丟失继低。
所以在 Kafka 集群比較大熬苍,分區(qū)數(shù)很多的時(shí)候,ZooKeeper 存儲(chǔ)的元數(shù)據(jù)就會(huì)很多,性能就差了柴底。
還有婿脸,ZooKeeper 也是分布式的,也需要選舉柄驻,它的選舉也不快狐树,而且發(fā)生選舉的那段時(shí)候是不提供服務(wù)的!
基于 ZooKeeper 的性能問(wèn)題 Kafka 之前就做了一些升級(jí)凿歼。
例如以前 Consumer 的位移數(shù)據(jù)是保存在 ZooKeeper 上的褪迟,所以當(dāng)提交位移或者獲取位移的時(shí)候都需要訪問(wèn) ZooKeeper ,這量一大 ZooKeeper 就頂不住答憔。
所以后面引入了位移主題(Topic 是 __consumer_offsets),將位移的提交和獲取當(dāng)做消息一樣來(lái)處理掀抹,存儲(chǔ)在日志中虐拓,避免了頻繁訪問(wèn) ZooKeeper 性能差的問(wèn)題。
還有像一些類似樂(lè)字節(jié)這樣的大公司傲武,可能要支持百萬(wàn)分區(qū)級(jí)別蓉驹,這目前的 Kafka 單集群架構(gòu)下是無(wú)法支持穩(wěn)定運(yùn)行的,也就是目前單集群可以承載的分區(qū)數(shù)有限揪利。
所以态兴,Kafka 需要去 ZooKeeper 。
所以沒(méi)了 Zookeeper 之后的 Kafka 的怎樣的疟位?
沒(méi)了 Zookeeper 的 Kafka 就把元數(shù)據(jù)存儲(chǔ)到自己內(nèi)部了瞻润,利用之前的 Log 存儲(chǔ)機(jī)制來(lái)保存元數(shù)據(jù)。
就和上面說(shuō)到的位移主題一樣甜刻,會(huì)有一個(gè)元數(shù)據(jù)主題绍撞,元數(shù)據(jù)會(huì)像普通消息一樣保存在 Log 中。
所以元數(shù)據(jù)和之前的位移一樣得院,利用現(xiàn)有的消息存儲(chǔ)機(jī)制稍加改造來(lái)實(shí)現(xiàn)了功能傻铣,完美!
然后還搞了個(gè) KRaft 來(lái)實(shí)現(xiàn) Controller Quorum祥绞。
這個(gè)協(xié)議是基于 Raft 的非洲,協(xié)議具體就不展開(kāi)了,就理解為它能解決 Controller Leader 的選舉蜕径,并且讓所有節(jié)點(diǎn)達(dá)成共識(shí)两踏。
在之前基于 Zookeeper 實(shí)現(xiàn)的單個(gè) Controller 在分區(qū)數(shù)太大的時(shí)候還有個(gè)問(wèn)題,故障轉(zhuǎn)移太慢了丧荐。
當(dāng) Controller 變更的時(shí)候缆瓣,需要重新加載所有的元數(shù)據(jù)到新的 Controller 身上,并且需要把這些元數(shù)據(jù)同步給集群內(nèi)的所有 Broker虹统。
而 Controller Quorum 中的 Leader 選舉切換則很快弓坞,因?yàn)樵獢?shù)據(jù)都已經(jīng)在 quorum 中同步了隧甚,也就是 quorum 的 Broker 都已經(jīng)有全部了元數(shù)據(jù),所以不需要重新加載元數(shù)據(jù)渡冻!
并且其它 Broker 已經(jīng)基于 Log 存儲(chǔ)了一些元數(shù)據(jù)戚扳,所以只需要增量更新即可,不需要全量了族吻。
這波改造下來(lái)就解決了之前元數(shù)據(jù)過(guò)多的問(wèn)題帽借,可以支持更多的分區(qū)!
最后
可能看到這里有人會(huì)說(shuō)超歌,那為何一開(kāi)始不這么實(shí)現(xiàn)砍艾?
因?yàn)?ZooKeeper 是一個(gè)功能強(qiáng)大且經(jīng)過(guò)驗(yàn)證的工具,在早期利用它來(lái)實(shí)現(xiàn)一些功能巍举,多簡(jiǎn)單喲脆荷,都不需要自己實(shí)現(xiàn)。
要不是 ZooKeeper 的機(jī)制導(dǎo)致了這個(gè)瓶頸懊悯,也不可能會(huì)有這個(gè)改造的蜓谋。
軟件就是這樣,沒(méi)必要重復(fù)造輪子炭分,合適就好桃焕。
PS:給大家推薦個(gè)特別牛的Kafka自學(xué)課程,B站:BV1Bf4y1W7B6