您好,登錄后才能下訂單哦!
這篇文章給大家介紹怎么保證RabbitMQ消息隊(duì)列的高可用,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。
如何保證消息隊(duì)列的高可用?
如果有人問到你 MQ 的知識(shí),高可用是必問的。MQ 會(huì)導(dǎo)致系統(tǒng)可用性降低。所以只要你用了 MQ,接下來(lái)問的一些要點(diǎn)肯定就是圍繞著 MQ 的那些缺點(diǎn)怎么來(lái)解決了。
要是你傻乎乎的就干用了一個(gè) MQ,各種問題從來(lái)沒考慮過,那你就杯具了,面試官對(duì)你的感覺就是,只會(huì)簡(jiǎn)單使用一些技術(shù),沒任何思考,馬上對(duì)你的印象就不太好了。這樣的同學(xué)招進(jìn)來(lái)要是做個(gè) 20k 薪資以內(nèi)的普通小弟還湊合,要是做薪資 20k+ 的高工,那就慘了,讓你設(shè)計(jì)個(gè)系統(tǒng),里面肯定一堆坑,出了事故公司受損失,團(tuán)隊(duì)一起背鍋。
這個(gè)問題這么問是很好的,因?yàn)椴荒軉柲?Kafka 的高可用性怎么保證?ActiveMQ 的高可用性怎么保證?一個(gè)面試官要是這么問就顯得很沒水平,人家可能用的就是 RabbitMQ,沒用過 Kafka,你上來(lái)問人家 Kafka 干什么?這不是擺明了刁難人么。
所以有水平的面試官,問的是 MQ 的高可用性怎么保證?這樣就是你用過哪個(gè) MQ,你就說說你對(duì)那個(gè) MQ 的高可用性的理解。
RabbitMQ 是比較有代表性的,因?yàn)槭?strong>基于主從(非分布式)做高可用性的,我們就以 RabbitMQ 為例子講解第一種 MQ 的高可用性怎么實(shí)現(xiàn)。
RabbitMQ 有三種模式:?jiǎn)螜C(jī)模式、普通集群模式、鏡像集群模式。
單機(jī)模式,就是 Demo 級(jí)別的,一般就是你本地啟動(dòng)了玩玩兒的 ????,沒人生產(chǎn)用單機(jī)模式。
普通集群模式,意思就是在多臺(tái)機(jī)器上啟動(dòng)多個(gè) RabbitMQ 實(shí)例,每個(gè)機(jī)器啟動(dòng)一個(gè)。你創(chuàng)建的 queue,只會(huì)放在一個(gè) RabbitMQ 實(shí)例上,但是每個(gè)實(shí)例都同步 queue 的元數(shù)據(jù)(元數(shù)據(jù)可以認(rèn)為是 queue 的一些配置信息,通過元數(shù)據(jù),可以找到 queue 所在實(shí)例)。你消費(fèi)的時(shí)候,實(shí)際上如果連接到了另外一個(gè)實(shí)例,那么那個(gè)實(shí)例會(huì)從 queue 所在實(shí)例上拉取數(shù)據(jù)過來(lái)。
這種方式確實(shí)很麻煩,也不怎么好,沒做到所謂的分布式,就是個(gè)普通集群。因?yàn)檫@導(dǎo)致你要么消費(fèi)者每次隨機(jī)連接一個(gè)實(shí)例然后拉取數(shù)據(jù),要么固定連接那個(gè) queue 所在實(shí)例消費(fèi)數(shù)據(jù),前者有數(shù)據(jù)拉取的開銷,后者導(dǎo)致單實(shí)例性能瓶頸。
而且如果那個(gè)放 queue 的實(shí)例宕機(jī)了,會(huì)導(dǎo)致接下來(lái)其他實(shí)例就無(wú)法從那個(gè)實(shí)例拉取,如果你開啟了消息持久化,讓 RabbitMQ 落地存儲(chǔ)消息的話,消息不一定會(huì)丟,得等這個(gè)實(shí)例恢復(fù)了,然后才可以繼續(xù)從這個(gè) queue 拉取數(shù)據(jù)。
所以這個(gè)事兒就比較尷尬了,這就沒有什么所謂的高可用性,這方案主要是提高吞吐量的,就是說讓集群中多個(gè)節(jié)點(diǎn)來(lái)服務(wù)某個(gè) queue 的讀寫操作。
這種模式,才是所謂的 RabbitMQ 的高可用模式。跟普通集群模式不一樣的是,在鏡像集群模式下,你創(chuàng)建的 queue,無(wú)論元數(shù)據(jù)還是 queue 里的消息都會(huì)存在于多個(gè)實(shí)例上,就是說,每個(gè) RabbitMQ 節(jié)點(diǎn)都有這個(gè) queue 的一個(gè)完整鏡像,包含 queue 的全部數(shù)據(jù)的意思。然后每次你寫消息到 queue 的時(shí)候,都會(huì)自動(dòng)把消息同步到多個(gè)實(shí)例的 queue 上。
那么如何開啟這個(gè)鏡像集群模式呢?其實(shí)很簡(jiǎn)單,RabbitMQ 有很好的管理控制臺(tái),就是在后臺(tái)新增一個(gè)策略,這個(gè)策略是鏡像集群模式的策略,指定的時(shí)候是可以要求數(shù)據(jù)同步到所有節(jié)點(diǎn)的,也可以要求同步到指定數(shù)量的節(jié)點(diǎn),再次創(chuàng)建 queue 的時(shí)候,應(yīng)用這個(gè)策略,就會(huì)自動(dòng)將數(shù)據(jù)同步到其他的節(jié)點(diǎn)上去了。
這樣的話,好處在于,你任何一個(gè)機(jī)器宕機(jī)了,沒事兒,其它機(jī)器(節(jié)點(diǎn))還包含了這個(gè) queue 的完整數(shù)據(jù),別的 consumer 都可以到其它節(jié)點(diǎn)上去消費(fèi)數(shù)據(jù)。壞處在于,第一,這個(gè)性能開銷也太大了吧,消息需要同步到所有機(jī)器上,導(dǎo)致網(wǎng)絡(luò)帶寬壓力和消耗很重!第二,這么玩兒,不是分布式的,就沒有擴(kuò)展性可言了,如果某個(gè) queue 負(fù)載很重,你加機(jī)器,新增的機(jī)器也包含了這個(gè) queue 的所有數(shù)據(jù),并沒有辦法線性擴(kuò)展你的 queue。你想,如果這個(gè) queue 的數(shù)據(jù)量很大,大到這個(gè)機(jī)器上的容量無(wú)法容納了,此時(shí)該怎么辦呢?
Kafka 一個(gè)最基本的架構(gòu)認(rèn)識(shí):由多個(gè) broker 組成,每個(gè) broker 是一個(gè)節(jié)點(diǎn);你創(chuàng)建一個(gè) topic,這個(gè) topic 可以劃分為多個(gè) partition,每個(gè) partition 可以存在于不同的 broker 上,每個(gè) partition 就放一部分?jǐn)?shù)據(jù)。
這就是天然的分布式消息隊(duì)列,就是說一個(gè) topic 的數(shù)據(jù),是分散放在多個(gè)機(jī)器上的,每個(gè)機(jī)器就放一部分?jǐn)?shù)據(jù)。
實(shí)際上 RabbmitMQ 之類的,并不是分布式消息隊(duì)列,它就是傳統(tǒng)的消息隊(duì)列,只不過提供了一些集群、HA(High Availability, 高可用性) 的機(jī)制而已,因?yàn)闊o(wú)論怎么玩兒,RabbitMQ 一個(gè) queue 的數(shù)據(jù)都是放在一個(gè)節(jié)點(diǎn)里的,鏡像集群下,也是每個(gè)節(jié)點(diǎn)都放這個(gè) queue 的完整數(shù)據(jù)。
Kafka 0.8 以前,是沒有 HA 機(jī)制的,就是任何一個(gè) broker 宕機(jī)了,那個(gè) broker 上的 partition 就廢了,沒法寫也沒法讀,沒有什么高可用性可言。
比如說,我們假設(shè)創(chuàng)建了一個(gè) topic,指定其 partition 數(shù)量是 3 個(gè),分別在三臺(tái)機(jī)器上。但是,如果第二臺(tái)機(jī)器宕機(jī)了,會(huì)導(dǎo)致這個(gè) topic 的 1/3 的數(shù)據(jù)就丟了,因此這個(gè)是做不到高可用的。
Kafka 0.8 以后,提供了 HA 機(jī)制,就是 replica(復(fù)制品) 副本機(jī)制。每個(gè) partition 的數(shù)據(jù)都會(huì)同步到其它機(jī)器上,形成自己的多個(gè) replica 副本。所有 replica 會(huì)選舉一個(gè) leader 出來(lái),那么生產(chǎn)和消費(fèi)都跟這個(gè) leader 打交道,然后其他 replica 就是 follower。寫的時(shí)候,leader 會(huì)負(fù)責(zé)把數(shù)據(jù)同步到所有 follower 上去,讀的時(shí)候就直接讀 leader 上的數(shù)據(jù)即可。只能讀寫 leader?很簡(jiǎn)單,要是你可以隨意讀寫每個(gè) follower,那么就要 care 數(shù)據(jù)一致性的問題,系統(tǒng)復(fù)雜度太高,很容易出問題。Kafka 會(huì)均勻地將一個(gè) partition 的所有 replica 分布在不同的機(jī)器上,這樣才可以提高容錯(cuò)性。
這么搞,就有所謂的高可用性了,因?yàn)槿绻硞€(gè) broker 宕機(jī)了,沒事兒,那個(gè) broker 上面的 partition 在其他機(jī)器上都有副本的。如果這個(gè)宕機(jī)的 broker 上面有某個(gè) partition 的 leader,那么此時(shí)會(huì)從 follower 中重新選舉一個(gè)新的 leader 出來(lái),大家繼續(xù)讀寫那個(gè)新的 leader 即可。這就有所謂的高可用性了。
寫數(shù)據(jù)的時(shí)候,生產(chǎn)者就寫 leader,然后 leader 將數(shù)據(jù)落地寫本地磁盤,接著其他 follower 自己主動(dòng)從 leader 來(lái) pull 數(shù)據(jù)。一旦所有 follower 同步好數(shù)據(jù)了,就會(huì)發(fā)送 ack 給 leader,leader 收到所有 follower 的 ack 之后,就會(huì)返回寫成功的消息給生產(chǎn)者。(當(dāng)然,這只是其中一種模式,還可以適當(dāng)調(diào)整這個(gè)行為)
消費(fèi)的時(shí)候,只會(huì)從 leader 去讀,但是只有當(dāng)一個(gè)消息已經(jīng)被所有 follower 都同步成功返回 ack 的時(shí)候,這個(gè)消息才會(huì)被消費(fèi)者讀到。
關(guān)于怎么保證RabbitMQ消息隊(duì)列的高可用就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。