新來(lái)個(gè)技術(shù)總監(jiān),把MQ高可用架構(gòu)講的那叫一個(gè)透徹
一、背景引入
這篇文章,我們來(lái)聊一下消息中間件高可用架構(gòu)的一些原理。
對(duì)于一個(gè)合格的高級(jí)Java工程師而言,你肯定會(huì)碰到在系統(tǒng)里用到MQ的場(chǎng)景,那么這個(gè)時(shí)候你需要基于你的業(yè)務(wù)場(chǎng)景和需求,考慮在使用MQ的時(shí)候可能遇到的一些技術(shù)問(wèn)題。
接著,你必須得針對(duì)這些技術(shù)問(wèn)題設(shè)計(jì)一套完整的技術(shù)方案。
你需要從消息的訂閱模式、消息的生產(chǎn)到消費(fèi)全鏈路不丟數(shù)據(jù)、消息中間件本身如何保證高可用,等各個(gè)角度切入,來(lái)考慮好你的系統(tǒng)和MQ對(duì)接之后的完整技術(shù)方案。
所以,本文就來(lái)聊聊消息中間件高可用的架構(gòu)原理。
二、先來(lái)思考一下消息中間件的可用性問(wèn)題
咱們先拋開(kāi)各種具體的技術(shù),就來(lái)思考一下,啥是MQ的可用性問(wèn)題?
大家看看下面的圖,其實(shí)道理很簡(jiǎn)單,假如你的MQ就部署在一臺(tái)機(jī)器上,那么正常情況下,生產(chǎn)者都會(huì)發(fā)送消息到MQ去,然后讓消費(fèi)者獲取到。
但是萬(wàn)一天有不測(cè)風(fēng)云,MQ部署的那臺(tái)機(jī)器,因?yàn)橐恍┠脑?,MQ自己本身的進(jìn)程掛掉了,或者是那臺(tái)機(jī)器直接就宕機(jī)了,那么此時(shí)怎么辦呢?
很尷尬,是不是,結(jié)果是很明顯的,生產(chǎn)者沒(méi)法發(fā)送數(shù)據(jù)出去,然后消費(fèi)者也沒(méi)法獲取到數(shù)據(jù)了。
然后整個(gè)系統(tǒng)不就完蛋了?因?yàn)橄到y(tǒng)的核心流程根本無(wú)法跑通了,對(duì)不對(duì)?
MQ宕機(jī)就直接導(dǎo)致你的系統(tǒng)本身也故障了,然后可能會(huì)導(dǎo)致你的公司對(duì)外的APP、網(wǎng)站等產(chǎn)品就無(wú)法運(yùn)作了,用戶(hù)無(wú)法使用你們公司的服務(wù)了。
如果你們公司是電商平臺(tái)、外賣(mài)平臺(tái)、社交平臺(tái)。那么來(lái)這么一出,不是會(huì)導(dǎo)致公司損失慘重?
如果你的系統(tǒng)持續(xù)幾個(gè)小時(shí)無(wú)法被人使用,本來(lái)你公司電商平臺(tái)一天營(yíng)收可以達(dá)到1億,結(jié)果現(xiàn)在導(dǎo)致幾個(gè)小時(shí)內(nèi)無(wú)法下單購(gòu)買(mǎi)商品,最后當(dāng)天營(yíng)收就5000萬(wàn),那么你的公司是不是直接活生生損失了5000萬(wàn)?
這個(gè)真的不是開(kāi)玩笑的,如果大家留意互聯(lián)網(wǎng)行業(yè)的新聞的話(huà)和小道消息的話(huà),就應(yīng)該知道近幾年一些大型互聯(lián)網(wǎng)公司都出現(xiàn)過(guò)類(lèi)似的情況,損失慘重,咱們做碼農(nóng)的就得被祭天了是不是?
三、集群化部署 + 數(shù)據(jù)多副本冗余
好,問(wèn)題來(lái)了!現(xiàn)在你感覺(jué)一個(gè)MQ中間件應(yīng)該如何實(shí)現(xiàn)高可用呢?
這里的方式有很多種,比如說(shuō)數(shù)據(jù)多副本冗余,集群鏡像同步機(jī)制,我們就拋開(kāi)具體的技術(shù)來(lái)從本質(zhì)層面思考一下MQ集群實(shí)現(xiàn)高可用的幾種方式。
先來(lái)看下面的一張圖,假設(shè)我們寫(xiě)到MQ的數(shù)據(jù)都被多副本冗余了,也就是你寫(xiě)的每一條消息都被復(fù)制到了其他的機(jī)器上去了。
那么此時(shí)任何一臺(tái)機(jī)器宕機(jī),似乎都不會(huì)影響我們跟MQ繼續(xù)通信,而且寫(xiě)出去的數(shù)據(jù)似乎也都還在。
?上面的圖里,MQ采用集群模式部署到了2臺(tái)機(jī)器上去,然后生產(chǎn)者給其中一臺(tái)機(jī)器寫(xiě)入一條消息,該機(jī)器自動(dòng)同步復(fù)制給另外一臺(tái)機(jī)器。
此時(shí)數(shù)據(jù)在2臺(tái)機(jī)器上,就有2個(gè)副本了,那么如果第一臺(tái)機(jī)器宕機(jī)了,會(huì)影響我們嗎?
答案是:不會(huì)。
因?yàn)閿?shù)據(jù)本身是多副本冗余的,此時(shí)消費(fèi)者完全?可以從第二臺(tái)機(jī)器消費(fèi)到這條消息,并且生產(chǎn)者還可以繼續(xù)給第二臺(tái)機(jī)器寫(xiě)入消息,數(shù)據(jù)沒(méi)丟失。
而且,系統(tǒng)根本不用中斷流程,還可以繼續(xù)運(yùn)行,我們看下面的圖。
這種感覺(jué)是不是很棒?實(shí)際上這種MQ集群化部署架構(gòu)以及數(shù)據(jù)多副本冗余機(jī)制,是非常常見(jiàn)的一種高可用架構(gòu)。
Kafka這個(gè)極為優(yōu)秀的消息中間件,就是采用的這種架構(gòu)保證高可用、數(shù)據(jù)容錯(cuò)性。
四、多副本同步復(fù)制強(qiáng)制要求
但是這里你要思考另外幾個(gè)問(wèn)題,第一個(gè)就是:你在寫(xiě)數(shù)據(jù)到其中一臺(tái)機(jī)器的時(shí)候,是不是得要求,必須得讓那臺(tái)機(jī)器復(fù)制數(shù)據(jù)到另外一臺(tái)機(jī)器了,保證集群里一定有這條數(shù)據(jù)雙副本了,才可以認(rèn)為本次寫(xiě)成功了?
沒(méi)錯(cuò),假如你要是不能保證這一點(diǎn),比如你就寫(xiě)數(shù)據(jù)給了其中一臺(tái)機(jī)器,然后他還沒(méi)來(lái)得及復(fù)制給另外一臺(tái)機(jī)器呢,直接第一臺(tái)機(jī)器就宕機(jī)了。
此時(shí)雖然你可以繼續(xù)基于第二臺(tái)機(jī)器發(fā)送消息和消費(fèi)消息,但是你剛才發(fā)送的一條消息就丟失了。
大家看下面的圖來(lái)理解一下這個(gè)場(chǎng)景。
所以對(duì)于采用這種機(jī)制的時(shí)候,你必須得讓生產(chǎn)者通過(guò)一些參數(shù)的設(shè)置,保證說(shuō)寫(xiě)一條消息到某臺(tái)機(jī)器,他必須同步這條消息到另外一臺(tái)機(jī)器成功,集群里有雙副本了,然后此時(shí)才可以認(rèn)為這條消息寫(xiě)成功了。
但凡剛寫(xiě)一臺(tái)機(jī)器他就宕機(jī),還沒(méi)來(lái)得及復(fù)制到另外一臺(tái)機(jī)器的話(huà),本次寫(xiě)應(yīng)該報(bào)錯(cuò)失敗,然后你應(yīng)該重試再次寫(xiě)入數(shù)據(jù)到MQ集群里去。
大家看看下面的圖。只要你一次寫(xiě)成功了,他就保證肯定已經(jīng)同步數(shù)據(jù)為雙副本了,此時(shí)哪怕一臺(tái)機(jī)器宕機(jī),數(shù)據(jù)不會(huì)丟失,生產(chǎn)和消費(fèi)都可以有條不紊的繼續(xù)進(jìn)行。
五、多機(jī)器承載多副本強(qiáng)制要求
?第二個(gè)問(wèn)題,假如說(shuō)現(xiàn)在你的集群中本來(lái)有兩臺(tái)機(jī)器,現(xiàn)在宕機(jī)了其中的一臺(tái),只有一臺(tái)機(jī)器了,你還能允許你的生產(chǎn)者對(duì)唯一的一臺(tái)機(jī)器繼續(xù)寫(xiě)入數(shù)據(jù)嗎?
答案是:否。
因?yàn)槿绻豪镏挥幸慌_(tái)機(jī)器可以承載寫(xiě)入,那么萬(wàn)一剩余的一臺(tái)機(jī)器又宕機(jī)了呢?是不是還是會(huì)導(dǎo)致數(shù)據(jù)丟失,集群完蛋?
所以說(shuō),你的生產(chǎn)者同理應(yīng)該基于參數(shù)設(shè)置一下,集群里必須有超過(guò)2臺(tái)機(jī)器可以接收你的數(shù)據(jù)副本復(fù)制。
否則如果只有1臺(tái)機(jī)器可以接受你的數(shù)據(jù)副本復(fù)制的話(huà),那么還是算了。
大家看看下面的圖,感受一下那個(gè)場(chǎng)景。?
假設(shè)集群里有3臺(tái)機(jī)器,那么其中一臺(tái)宕機(jī)了,你后續(xù)再寫(xiě)入另外一臺(tái)的時(shí)候,判斷一下集群里還有剩余兩臺(tái)機(jī)器,足以保證數(shù)據(jù)雙副本的高可用性和容錯(cuò)性,所以可以繼續(xù)正常的寫(xiě)入數(shù)據(jù)到MQ集群里去。
實(shí)際上,上面說(shuō)的那一整套的機(jī)制,在Kafka里都可以采用,他有對(duì)應(yīng)的一些參數(shù)可以配置數(shù)據(jù)有幾個(gè)副本,包括你每次寫(xiě)入必須復(fù)制到幾臺(tái)機(jī)器才可以算成功,否則就要重新發(fā)送,以及你的集群剩余機(jī)器必須可以承載幾個(gè)副本才能繼續(xù)寫(xiě)入數(shù)據(jù)。
通過(guò)這一整套方案的設(shè)計(jì)和基于具體技術(shù)的落地,才可以保證在集群化部署的情況下,集群必須有幾臺(tái)機(jī)器承載多副本,同時(shí)數(shù)據(jù)寫(xiě)入之后必須是保證多副本冗余的。
此時(shí),任何機(jī)器宕機(jī),數(shù)據(jù)都不會(huì)丟失,還可以正常讓系統(tǒng)繼續(xù)運(yùn)行。
六、架構(gòu)原理與技術(shù)無(wú)關(guān)性
其實(shí)本文對(duì)消息中間件的集群高可用架構(gòu)的探討,是完全脫離于某個(gè)具體技術(shù)的,非常樸素的從本質(zhì)的原理層面來(lái)討論這個(gè)話(huà)題。
具體的RabbitMQ、Kafka、RocketMQ等各種不同的消息中間件,對(duì)這種高可用架構(gòu)的實(shí)現(xiàn),都有一定的相似想通性,但是也都有各自不同的技術(shù)實(shí)現(xiàn),以及相對(duì)應(yīng)的區(qū)別。