1. 一文理解消息隊(duì)列如何保證高可用

        共 4902字,需瀏覽 10分鐘

         ·

        2021-06-12 14:33

        之前博客《一文理解為什么需要使用消息隊(duì)列》提到過,系統(tǒng)引入消息隊(duì)列后,需要考慮如何保證消息隊(duì)列的高可用。

        本篇文章將圍繞幾個(gè)常見的消息隊(duì)列中間件(RabbitMQ,RocketMQ,Kafka)進(jìn)行逐個(gè)講解。

        RabbitMQ

        RabbitMQ 有三種模式:單機(jī)模式、普通集群模式、鏡像集群模式。

        單機(jī)模式

        單機(jī)模式,一般是開發(fā)者本地啟動調(diào)試使用,不會應(yīng)用到生產(chǎn)環(huán)境。

        普通集群模式

        普通集群模式下,在多臺機(jī)器上分別啟動一個(gè)RabbitMQ實(shí)例。新創(chuàng)建的queue,只會放在其中一個(gè)RabbitMQ實(shí)例上,但是每個(gè)實(shí)例都同步queue的元數(shù)據(jù)(元數(shù)據(jù)是queue的一些配置信息,例如通過元數(shù)據(jù)可以找到queue所在實(shí)例)。在消費(fèi)者進(jìn)行消費(fèi)的時(shí)候,如果連接到的實(shí)例沒有指定的queue,那么這個(gè)實(shí)例會從queue所在實(shí)例上拉取數(shù)據(jù)過來。

        這種模式下,要么消費(fèi)者每次隨機(jī)連接一個(gè)實(shí)例然后拉取數(shù)據(jù),要么固定連接指定queue所在實(shí)例消費(fèi)數(shù)據(jù),前者有數(shù)據(jù)拉取的開銷,后者可能會導(dǎo)致單實(shí)例性能瓶頸。

        缺點(diǎn):

        1. 性能開銷大,不同節(jié)點(diǎn)間的數(shù)據(jù)傳輸,可能會導(dǎo)致網(wǎng)絡(luò)帶寬壓力和消耗很重。

        2. 如果某個(gè)queue實(shí)例宕機(jī),會導(dǎo)致節(jié)點(diǎn)接下來其他實(shí)例就無法從那個(gè)實(shí)例拉取消息。即時(shí)開啟了消息持久化,在該節(jié)點(diǎn)重啟的過程中,對外服務(wù)也是中斷。

        普通集群模式相對單機(jī)模式,提升了消費(fèi)速度,提高了吞吐量。

        鏡像集群模式

        這種模式下RabbitMQ才能實(shí)現(xiàn)高可用。跟普通集群模式不一樣的是,在鏡像集群模式下,創(chuàng)建的queue,無論元數(shù)據(jù)還是queue里的消息都會完整存在于多個(gè)實(shí)例上。

        這樣就可以保證任何一個(gè)節(jié)點(diǎn)宕機(jī)后,其他節(jié)點(diǎn)還包含了這個(gè)queue的完整數(shù)據(jù),consumer可以到其他的節(jié)點(diǎn)上去消費(fèi)數(shù)據(jù)。

        缺點(diǎn):

        1. 性能開銷大,消息需要同步到多個(gè)節(jié)點(diǎn),導(dǎo)致網(wǎng)絡(luò)帶寬壓力和消耗很重。

        2. 節(jié)點(diǎn)沒有拓展性。如果某個(gè)queue負(fù)載過重,即使添加新的RabbitMQ節(jié)點(diǎn),也需要包含這個(gè)queue的所有數(shù)據(jù)。

        注:

        1. 指定queue的消息同時(shí)存在節(jié)點(diǎn)的數(shù)量是可以通過RabbitMQ控制臺配置進(jìn)行設(shè)置。

        鏡像集群模式相對普通集群模式,提升了可用性,但對吞吐量沒有改善。

        RocketMQ

        RocketMQ的集群方式分為:

        1. 多Master模式

        2. 多Master多Slave異步模式(一般生產(chǎn)環(huán)境使用)

        3. 多Master多Slave同步模式(對數(shù)據(jù)可靠性要求高時(shí)使用)

        RocketMQ中由NameServer集群、Broker 集群、Producer 集群和Consumer集群組成。

        1. NameServer: 提供輕量級的服務(wù)發(fā)現(xiàn)和路由。每個(gè)NameServer記錄完整的路由信息,提供等效的讀寫服務(wù),并支持快速存儲擴(kuò)展。

        2. Broker: 通過提供輕量級的 Topic 和 Queue 機(jī)制來處理消息存儲,同時(shí)支持推(push)和拉(pull)模式以及主從結(jié)構(gòu)的容錯(cuò)機(jī)制。

        3. Producer:生產(chǎn)者,產(chǎn)生消息的實(shí)例,擁有相同Producer Group的Producer組成一個(gè)集群。

        4. Consumer:消費(fèi)者,接收消息進(jìn)行消費(fèi)的實(shí)例,擁有相同Consumer Group的Consumer組成一個(gè)集群。

        RocketMQ是通過Broker主從機(jī)制來實(shí)現(xiàn)高可用的。相同Broker名稱,不同Brokerid的機(jī)器組成一個(gè)Broker組,BrokerId=0表明這個(gè)Broker是Master,BrokerId>0表明這個(gè)Broker是Slave。

        消息生產(chǎn)的高可用:創(chuàng)建Topic時(shí),把Topic的多個(gè)message queue創(chuàng)建在多個(gè)broker組上。這樣當(dāng)一個(gè)Broker組的Master不可用后,Producer仍然可以給其他組的Master發(fā)送消息。

        消息消費(fèi)的高可用:Consumer并不能配置從Master讀還是Slave讀。當(dāng)Master不可用或者繁忙的時(shí)候,Consumer會被自動切換到從Slave讀。這樣當(dāng)Master出現(xiàn)故障后,Consumer仍然可以從Slave讀,保證了消息消費(fèi)的高可用。

        可以理解為:Rocketmq是通過多個(gè)Master實(shí)現(xiàn)寫入容災(zāi),通過主從實(shí)現(xiàn)讀取容災(zāi)。

        上圖中,Broker Master1和Broker Slave1 是主從結(jié)構(gòu),實(shí)例之間會進(jìn)行數(shù)據(jù)同步。同時(shí)每個(gè)Broker與NameServer集群中的所有節(jié)點(diǎn)建立長連接,定時(shí)注冊Topic信息到所有NameServer中。

        Producer與NameServer集群中的其中一個(gè)節(jié)點(diǎn)(隨機(jī)選擇)建立長連接,定期從NameServer獲取Topic路由信息,并向提供Topic服務(wù)的Broker Master建立長連接,且定時(shí)向Broker發(fā)送心跳。Producer只能將消息發(fā)送到Broker Master;是Consumer則不一樣,它同時(shí)和提供Topic服務(wù)的Master和Slave建立長連接,既可以從Broker Master訂閱消息,也可以從Broker Slave訂閱消息。

        在RocketMQ里面,1臺機(jī)器要么是Master,要么是Slave,這在初始的機(jī)器配置里面就確定了。其中Master的Broker id = 0,Slave的Broker id > 0。有點(diǎn)類似于MySQL的主從概念,Master掛了以后,Slave仍然可以提供讀服務(wù),但是由于有多主的存在,當(dāng)一個(gè)Master掛了以后,可以寫到其他的Master上。

        2.1 多Master模式

        只有Master,無Slave。某個(gè)實(shí)例掛了,該實(shí)例在重啟前未被消費(fèi)的消息無法被消費(fèi)。

        優(yōu)點(diǎn):配置簡單,性能最高。

        缺點(diǎn):單臺機(jī)器重啟或宕機(jī)期間,該機(jī)器下未被消費(fèi)的消息在機(jī)器恢復(fù)前不可訂閱,影響消息實(shí)時(shí)性。

        2.2. 多Master多Slave異步模式

        每個(gè)Master配一個(gè)Slave,有多對Master-Slave,集群采用異步復(fù)制方式,主備有短暫消息延遲,毫秒級

        優(yōu)點(diǎn):性能同多Master幾乎一樣,實(shí)時(shí)性高,主備間切換對應(yīng)用透明,不需人工干預(yù)。

        缺點(diǎn):Master宕機(jī)或磁盤損壞時(shí)會有少量消息丟失。

        2.3. 多Master多Slave同步模式

        每個(gè)Master配一個(gè)Slave,有多對Master-Slave,集群采用同步雙寫方式,主備都寫成功,才向應(yīng)用返回成功

        優(yōu)點(diǎn):服務(wù)可用性與數(shù)據(jù)可用性非常高。

        缺點(diǎn):性能比異步集群略低(大約低10%)。

        Kafka

        kafka 0.8以前,是沒有HA機(jī)制的,就是任何一個(gè)Broker宕機(jī)了,那個(gè)Broker上的Partition就沒法寫也沒法讀,無法實(shí)現(xiàn)高可用性。

        Kafka 0.8版本以后,增加了replica副本機(jī)制,從而實(shí)現(xiàn)了Kafka的高可用性。

        基礎(chǔ)知識

        如果對Kafka不了解的話,可以先看這篇博客《一文快速了解Kafka》。

        消息傳遞同步策略

        Producer在發(fā)布消息到某個(gè)Partition時(shí),先通過ZooKeeper找到該P(yáng)artition的Leader,然后無論該Topic的Replication Factor為多少,Producer只將該消息發(fā)送到該P(yáng)artition的Leader。Leader會將該消息寫入其本地Log。每個(gè)Follower都從Leader pull數(shù)據(jù)。這種方式上,F(xiàn)ollower存儲的數(shù)據(jù)順序與Leader保持一致。Follower在收到該消息并寫入其Log后,向Leader發(fā)送ACK。當(dāng)Leader收到了ISR中的所有Replica的ACK,該消息就被認(rèn)為已經(jīng)commit了,Leader將增加HW并且向Producer發(fā)送ACK。

        為了提高性能,每個(gè)Follower在接收到數(shù)據(jù)后就立馬向Leader發(fā)送ACK,而非等到數(shù)據(jù)寫入Log中。因此,對于已經(jīng)commit的消息,Kafka只能保證它被存于多個(gè)Replica的內(nèi)存中,而不能保證它們被持久化到磁盤中,也就不能完全保證異常發(fā)生后該條消息一定能被Consumer消費(fèi)。

        Consumer讀消息也是從Leader讀取,只有被commit過的消息才會暴露給Consumer。

        Kafka Replication的數(shù)據(jù)流如下圖所示:

        Kafka高可用機(jī)制

        每個(gè)Partition的數(shù)據(jù)都會同步到其他機(jī)器上,形成自己的多個(gè)replica副本。然后所有replica會選舉一個(gè)leader出來,那么生產(chǎn)和消費(fèi)都跟這個(gè)leader打交道,然后其他replica就是follower。寫的時(shí)候,leader會負(fù)責(zé)把數(shù)據(jù)同步到所有follower上去,讀的時(shí)候就直接讀leader上數(shù)據(jù)即可。只能讀寫leader?很簡單,要是你可以隨意讀寫每個(gè)follower,那么就要care數(shù)據(jù)一致性的問題,系統(tǒng)復(fù)雜度太高,很容易出問題。kafka會均勻的將一個(gè)partition的所有replica分布在不同的機(jī)器上,這樣才可以提高容錯(cuò)性。

        kafka的這種機(jī)制,就有所謂的高可用性了,因?yàn)槿绻硞€(gè)broker宕機(jī)了,也沒事兒,因?yàn)槟莻€(gè)broker上面的partition在其他機(jī)器上都有副本的,那么此時(shí)會重新選舉一個(gè)新的leader出來,大家繼續(xù)讀寫那個(gè)新的leader即可。這就有所謂的高可用性了。

        1. 寫過程

        寫數(shù)據(jù)的時(shí)候,生產(chǎn)者就寫leader,然后leader將數(shù)據(jù)落地寫本地磁盤,接著其他follower自己主動從leader來pull數(shù)據(jù)。一旦所有follower同步好數(shù)據(jù)了,就會發(fā)送ack給leader,leader收到所有follower的ack之后,就會返回寫成功的消息給生產(chǎn)者。(當(dāng)然,這只是其中一種模式,還可以適當(dāng)調(diào)整這個(gè)行為)

        1. 讀過程

        消費(fèi)的時(shí)候,只會從Leader去讀,但是只有當(dāng)一個(gè)消息已經(jīng)被所有follower都同步成功并返回ack的時(shí)候,這個(gè)消息才能夠被消費(fèi)者讀到。

        對比RocketMQ與Kafka的架構(gòu)區(qū)別

        1. namesrv VS zk(不考慮Kafka2.8的Raft元數(shù)據(jù)模式)

        Kafka通過Zookeeper來進(jìn)行協(xié)調(diào),而RocketMq通過自身的namesrv進(jìn)行協(xié)調(diào):

        • Kafka在具備選舉功能,在Kafka里面,Master/Slave的選舉,有2步:第1步,先通過ZK在所有機(jī)器中,選舉出一個(gè)KafkaController;第2步,再由這個(gè)Controller,決定每個(gè)partition的Master是誰,Slave是誰。因?yàn)橛辛诉x舉功能,所以kafka某個(gè)partition的master掛了,該partition對應(yīng)的某個(gè)slave會升級為主對外提供服務(wù)。

        • RocketMQ不具備選舉,Master/Slave的角色也是固定的。當(dāng)一個(gè)Master掛了之后,你可以寫到其他Master上,但不能讓一個(gè)Slave切換成Master。那么rocketMq是如何實(shí)現(xiàn)高可用的呢,其實(shí)很簡單,rocketMq的所有broker節(jié)點(diǎn)的角色都是一樣,上面分配的topic和對應(yīng)的queue的數(shù)量也是一樣的,Mq只能保證當(dāng)一個(gè)broker掛了,把原本寫到這個(gè)broker的請求遷移到其他broker上面,而并不是這個(gè)broker對應(yīng)的slave升級為主。

        1. 吞吐量的對比

        • Kafka在消息存儲過程中會根據(jù)Partition的數(shù)量創(chuàng)建物理文件,例如創(chuàng)建一個(gè)topic并指定了3個(gè)Partition,那么就會有3個(gè)物理文件。

        • RocketMQ使用commitLog進(jìn)行消息存儲(順序?qū)懀S機(jī)讀),相當(dāng)于只有一個(gè)物理文件。

        Kafka的多文件并發(fā)寫入相對RocketMQ的單文件寫入,Kafka的性能要好很多。但Kafka的大量文件存儲會導(dǎo)致一個(gè)問題:當(dāng)Broker中包含Partition特別多的時(shí)候,磁盤的訪問會發(fā)生很大的瓶頸,畢竟單個(gè)文件看著是append操作,但是多個(gè)文件之間必然會導(dǎo)致磁盤的尋道。


        瀏覽 38
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評論
        圖片
        表情
        推薦
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
          
          

            1. 日韩性公交车上强videos | 女人被弄到高潮视频在线观看 | 在线肏屄视频 | 日韩精品人妻在线高清不卡一区二区 | 日本乱伦免费中文网 |