Kafka不停機(jī),如何無感知遷移ZooKeeper集群?

Kafka 在 Yelp 的應(yīng)用十分廣泛,Yelp 每天通過各種集群發(fā)送數(shù)十億條消息,在這背后,Kafka 使用 Zookeeper 完成各種分布式協(xié)調(diào)任務(wù)。
因?yàn)閅elp 非常依賴 Kafka,那么問題來了,它是否可以在不引起 Kafka 及其他 Zookeeper 用戶注意的情況下切換 Zookeeper 集群呢?本文將揭曉答案。
Kafka 在 Yelp 的應(yīng)用十分廣泛。事實(shí)上,我們 每天通過各種集群發(fā)送數(shù)十億條消息。在這背后,Kafka 使用 Zookeeper 完成各種分布式協(xié)調(diào)任務(wù),例如決定哪個 Kafka broker 負(fù)責(zé)分配分區(qū)首領(lǐng),以及在 broker 中存儲有關(guān)主題的元數(shù)據(jù)。
Kafka 在 Yelp 的成功應(yīng)用說明了我們的集群從其首次部署 Kafka 以來經(jīng)歷了大幅的增長。與此同時,其他的 Zookeeper 重度用戶(例如 Smartstack 和 PaasTA)規(guī)模也在增長,給我們的共享 Zookeeper 集群添加了很多負(fù)擔(dān)。為了緩解這種情況,我們決定讓我們的 Kafka 集群使用專門的 Zookeeper 集群。
由于我們非常依賴 Kafka,因維護(hù)造成的任何停機(jī)都會導(dǎo)致連鎖反應(yīng),例如顯示給業(yè)務(wù)所有者的儀表盤出現(xiàn)延遲、日志堆積在服務(wù)器上。那么問題就來了:我們是否可以在不引起 Kafka 及其他 Zookeeper 用戶注意的情況下切換 Zookeeper 集群?
Zookeeper 有絲分裂
經(jīng)過團(tuán)隊(duì)間對 Kafka 和 Zookeeper 的幾輪討論和頭腦風(fēng)暴之后,我們找到了一種方法,似乎可以實(shí)現(xiàn)我們的目標(biāo):在不會導(dǎo)致 Kafka 停機(jī)的情況下讓 Kafka 集群使用專門的 Zookeeper 集群。
我們提出的方案可以比作自然界的 細(xì)胞有絲分裂:我們復(fù)制 Zookeeper 主機(jī)(即 DNA),然后利用防火墻規(guī)則(即細(xì)胞壁)把復(fù)制好的主機(jī)分成兩個獨(dú)立的集群。

創(chuàng)新互聯(lián)于2013年成立,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目成都網(wǎng)站建設(shè)、網(wǎng)站建設(shè)網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元蘿北做網(wǎng)站,已為上家服務(wù),為蘿北各地企業(yè)和個人服務(wù),聯(lián)系電話:028-86922220

Kafka不停機(jī),如何無感知遷移ZooKeeper集群?

有絲分裂中的主要事件,染色體在細(xì)胞核中分裂
讓我們一步一步深入研究細(xì)節(jié)。在本文中,我們將會用到源集群和目標(biāo)集群,源集群代表已經(jīng)存在的集群,目標(biāo)集群代表 Kafka 將要遷移到的新集群。我們要用到的示例是一個包含三個節(jié)點(diǎn)的 Zookeeper 集群,但這個過程本身可用于任何數(shù)量的節(jié)點(diǎn)。
我們的示例將為 Zookeeper 節(jié)點(diǎn)使用以下 IP 地址:
源 192.168.1.1-3
目標(biāo) 192.168.1.4-6
第 1 階段:DNA 復(fù)制
首先,我們需要啟動一個新的 Zookeeper 集群。這個目標(biāo)集群必須是空的,因?yàn)樵谶w移的過程中,目標(biāo)集群中的內(nèi)容將被刪除。
然后,我們將目標(biāo)集群中的兩個節(jié)點(diǎn)和源集群中的三個節(jié)點(diǎn)組合在一起,得到一個包含五個節(jié)點(diǎn)的 Zookeeper 集群。這么做的原因是我們希望數(shù)據(jù)(最初由 Kafka 保存在源 Zookeeper 集群中)被復(fù)制到目標(biāo)集群上。Zookeeper 的復(fù)制機(jī)制會自動執(zhí)行復(fù)制過程。
Kafka不停機(jī),如何無感知遷移ZooKeeper集群?

把來自源集群和目標(biāo)集群的節(jié)點(diǎn)組合在一起
每個節(jié)點(diǎn)的 zoo.cfg 文件現(xiàn)在看起來都像下面這樣,包含源集群的所有節(jié)點(diǎn)和目標(biāo)集群中的兩個節(jié)點(diǎn):
server.1=192.168.1.1:2888:3888
server.2=192.168.1.2:2888:3888
server.3=192.168.1.3:2888:3888
server.4=192.168.1.4:2888:3888
server.5=192.168.1.5:2888:3888
注意,來自目標(biāo)集群的一個節(jié)點(diǎn)(在上面的例子中是 192.168.1.6)在該過程中保持休眠狀態(tài),沒有成為聯(lián)合集群的一部分,并且 Zookeeper 也沒有在其上運(yùn)行,這是為了保持源集群的 quorum。
此時,聯(lián)合集群必須重啟。確保執(zhí)行一次滾動重啟(每次重啟一個節(jié)點(diǎn),期間至少有 10 秒的時間間隔),從來自目標(biāo)集群的兩個節(jié)點(diǎn)開始。這個順序可以確保源集群的 quorum 不會丟失,并在新節(jié)點(diǎn)加入該集群時確保對其他客戶端(如 Kafka)的可用性。
Zookeeper 節(jié)點(diǎn)滾動重啟后,Kafka 對聯(lián)合集群中的新節(jié)點(diǎn)一無所知,因?yàn)樗?Zookeeper 連接字符串只有原始源集群的 IP 地址:
zookeeper.connect=192.168.1.1,192.168.1.2,192.168.1.3/kafka
發(fā)送給 Zookeeper 的數(shù)據(jù)現(xiàn)在被復(fù)制到新節(jié)點(diǎn),而 Kafka 甚至都沒有注意到。
現(xiàn)在,源集群和目標(biāo)集群之間的數(shù)據(jù)同步了,我們就可以更新 Kafka 的連接字符串,以指向目標(biāo)集群:
zookeeper.connect=192.168.1.4,192.168.1.5,192.168.1.6/kafka
需要來一次 Kafka 滾動重啟,以獲取新連接,但不要進(jìn)行整體停機(jī)。
第 2 階段:有絲分裂
拆分聯(lián)合集群的第一步是恢復(fù)原始源 Zookeeper 及目標(biāo) Zookeeper 的配置文件(zoo.cfg),因?yàn)樗鼈兎从沉思核璧淖罱K狀態(tài)。注意,此時不應(yīng)重啟 Zookeeper 服務(wù)。
我們利用防火墻規(guī)則來執(zhí)行有絲分裂,把我們的聯(lián)合集群分成不同的源集群和目標(biāo)集群,每個集群都有自己的首領(lǐng)。在我們的例子中,我們使用 iptables 來實(shí)現(xiàn)這一點(diǎn),但其實(shí)可以兩個 Zookeeper 集群主機(jī)之間強(qiáng)制使用的防火墻系統(tǒng)應(yīng)該都是可以的。
對每個目標(biāo)節(jié)點(diǎn),我們運(yùn)行以下命令來添加 iptables 規(guī)則:
$source_node_list = 192.168.1.1,192.168.1.2,192.168.1.3
sudo /sbin/iptables -v -A INPUT -p tcp -d $source_node_list -j REJECT
sudo /sbin/iptables -v -A OUTPUT -p tcp -d $source_node_list -j REJECT
這將拒絕從目標(biāo)節(jié)點(diǎn)到源節(jié)點(diǎn)的任何傳入或傳出 TCP 流量,從而實(shí)現(xiàn)兩個集群的分隔。

Kafka不停機(jī),如何無感知遷移ZooKeeper集群?

通過防火墻規(guī)則分隔源集群和目標(biāo)集群,然后重啟
分隔意味著現(xiàn)在兩個目標(biāo)節(jié)點(diǎn)與其他節(jié)點(diǎn)是分開的。因?yàn)樗鼈冋J(rèn)為自己屬于一個五節(jié)點(diǎn)的集群,而且無法與集群的大多數(shù)節(jié)點(diǎn)進(jìn)行通信,所以它們無法進(jìn)行首領(lǐng)選舉。
此時,我們同時重啟目標(biāo)集群中每個節(jié)點(diǎn)的 Zookeeper,包括那個不屬于聯(lián)合集群的休眠節(jié)點(diǎn)。這樣 Zookeeper 進(jìn)程將使用步驟 2 中提供的新配置,而且還會強(qiáng)制在目標(biāo)集群中進(jìn)行首領(lǐng)選舉,從而每個集群都會有自己的首領(lǐng)。
從 Kafka 的角度來看,目標(biāo)集群從發(fā)生網(wǎng)絡(luò)分區(qū)那一刻起就不可用,直到首領(lǐng)選舉結(jié)束后才可用。對 Kafka 來說,這是整個過程中 Zookeeper 不可用的唯一一個時間段。從現(xiàn)在開始,我們有了兩個不同的 Zookeeper 集群。
現(xiàn)在我們要做的是清理。源集群仍然認(rèn)為自己還有兩個額外的節(jié)點(diǎn),我們需要清理一些防火墻規(guī)則。
接下來,我們重啟源集群,讓只包含原始源集群節(jié)點(diǎn)的 zoo.cfg 配置生效。我們現(xiàn)在可以安全地刪除防火墻規(guī)則,因?yàn)榧褐g不再需要相互通信。下面的命令用于刪除 iptables 規(guī)則:
$source_node_list = 192.168.1.1,192.168.1.2,192.168.1.3
sudo /sbin/iptables -v -D INPUT -p tcp -d $source_node_list -j REJECT
sudo /sbin/iptables -v -D OUTPUT -p tcp -d $source_node_list -j REJECT
樹立信心分布式壓力測試
我們用于測試遷移過程正確性的主要方法是分布式壓力測試。在遷移過程中,我們通過腳本在多臺機(jī)器上運(yùn)行數(shù)十個 Kafka 生產(chǎn)者和消費(fèi)者實(shí)例。當(dāng)流量生成完成后,所有被消費(fèi)的數(shù)據(jù)有效載荷被聚集到單臺主機(jī)上,以便檢測是否發(fā)生數(shù)據(jù)丟失。
分布式壓力測試的工作原理是為 Kafka 生產(chǎn)者和消費(fèi)者創(chuàng)建一組 Docker 容器,并在多臺主機(jī)上并行運(yùn)行它們。所有生成的消息都包含了一個序列號,可以用于檢測是否發(fā)生消息丟失。
臨時集群
為了證明遷移的正確性,我們需要構(gòu)建一些專門用于測試的集群。我們不是通過手動創(chuàng)建 Kafka 集群,然后在測試完以后再關(guān)掉它們,而是構(gòu)建了一個工具,可以在我們的基礎(chǔ)架構(gòu)上自動生成和關(guān)閉集群,從而可以通過腳本來執(zhí)行整個測試過程。
這個工具連接到 AWS EC2 API 上,并用特定的 EC2 實(shí)例標(biāo)簽激活多臺主機(jī),允許我們的 puppet 代碼配置主機(jī)和安裝 Kafka(通過 External Node Classifiers
這個臨時集群腳本后來被用于創(chuàng)建臨時 Elasticsearch 集群進(jìn)行集成測試,這證明了它是一個非常有用的工具。
zk-smoketest
我們發(fā)現(xiàn),phunt 的 Zookeeper smoketest 腳本 Zookeeper 集群的狀態(tài)。在遷移的每個階段,我們在后臺運(yùn)行 smoketest,以確保 Zookeeper 集群的行為符合預(yù)期。
zkcopy
我們的第一個用于遷移的計(jì)劃涉及關(guān)閉 Kafka、把 Zookeeper 數(shù)據(jù)子集復(fù)制到新集群、使用更新過的 Zookeeper 連接重啟 Kafka。遷移過程的一個更精細(xì)的版本——我們稱之為“阻止和復(fù)制(block & copy)”——被用于把 Zookeeper 客戶端遷移到存有數(shù)據(jù)的集群,這是因?yàn)椤坝薪z分裂”過程需要一個空白的目標(biāo) Zookeeper 集群。用于復(fù)制 Zookeeper 數(shù)據(jù)子集的工具是 zkcopy,它可以把 Zookeeper 集群的子樹復(fù)制到另一個集群中。
我們還添加了事務(wù)支持,讓我們可以批量管理 Zookeeper 操作,并最大限度地減少為每個 znode 創(chuàng)建事務(wù)的網(wǎng)絡(luò)開銷。這使我們使用 zkcopy 的速度提高了約 10 倍。
另一個加速遷移過程的核心功能是“mtime”支持,它允許我們跳過復(fù)制早于給定修改時間的節(jié)點(diǎn)。我們因此避免了讓 Zookeeper 集群保持同步的第 2 個“catch-up”復(fù)制所需的大部分工作。Zookeeper 的停機(jī)時間從 25 分鐘減少為不到 2 分鐘。
經(jīng)驗(yàn)教訓(xùn)
Zookeeper 集群是輕量級的,如果有可能,盡量不要在不同服務(wù)之間共享它們,因?yàn)樗鼈兛赡軙?Zookeeper 的性能問題,這些問題很難調(diào)試,并且通常需要停機(jī)進(jìn)行修復(fù)。
我們可以在 Kafka 不停機(jī)的情況下讓 Kafka 使用新的 Zookeeper 集群,但是,這肯定不是一件小事。
如果在進(jìn)行 Zookeeper 遷移時允許 Kafka 停機(jī),那就簡單多了。
歡迎學(xué)Java和大數(shù)據(jù)的朋友們加入java架構(gòu)交流: 855835163
加群鏈接:https://jq.qq.com/?_wv=1027&k=5dPqXGI
群內(nèi)提供免費(fèi)的架構(gòu)資料還有:Java工程化、高性能及分布式、高性能、深入淺出。高架構(gòu)。性能調(diào)優(yōu)、Spring,MyBatis,Netty源碼分析和大數(shù)據(jù)等多個知識點(diǎn)高級進(jìn)階干貨的免費(fèi)直播講解 ?可以進(jìn)來一起學(xué)習(xí)交流哦

分享名稱:Kafka不停機(jī),如何無感知遷移ZooKeeper集群?
標(biāo)題路徑:http://bm7419.com/article28/ijpscp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站建設(shè)、網(wǎng)站策劃關(guān)鍵詞優(yōu)化、手機(jī)網(wǎng)站建設(shè)、網(wǎng)站制作、網(wǎng)站設(shè)計(jì)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

小程序開發(fā)