天天看點

大廠原來都是這樣實作分布式消息隊列的高可用RabbitMQ 高可用kafka的高可用性

MQ的高可用性怎麼保證?這樣就是你用過哪個MQ,你就說說你對那個MQ的高可用性的了解。

RabbitMQ 高可用

因為是基于主從做高可用性的,Rabbitmq有三種模式:單機模式,普通叢集模式,鏡像叢集模式

單機模式

demo級,本地啟動了玩玩兒的。

普通叢集模式

在多台機器啟動多個RabbitMQ執行個體,每個機器啟動一個

但你建立的queue,隻會放在一個RabbitMQ執行個體,但每個執行個體都同步queue的中繼資料。

完了你消費時,實際上如果連接配接到了另外一個執行個體,那麼那個執行個體會從queue所在執行個體上拉資料過來。

這種方式确實很麻煩,也不怎麼好,沒做到所謂的分布式,就是個普通叢集。

因為這導緻

  • 要麼消費者每次随機連接配接一個執行個體然後拉取資料

    有資料拉取的開銷

  • 要麼固定連接配接那個queue所在執行個體消費資料

    存在單執行個體的性能瓶頸

而且如果那個放queue的執行個體當機了,會導緻接下來其他執行個體就無法從那個執行個體拉取,如果你開啟了消息持久化,讓RabbitMQ落地存儲消息的話,消息不一定會丢,得等這個執行個體恢複了,然後才可以繼續從這個queue拉取資料。

這就沒有什麼所謂的高可用性可言了,這方案主要是提高吞吐量,即讓叢集中多個節點來服務某個queue的讀寫操作。

架構圖如下所示

大廠原來都是這樣實作分布式消息隊列的高可用RabbitMQ 高可用kafka的高可用性

鏡像叢集模式

這種才是RabbitMQ高可用模式,跟普通叢集模式不一樣的是,你建立的queue,無論中繼資料還是queue裡的消息都會存在于多個執行個體。

然後每次你寫消息到queue時,都會自動把消息到多個執行個體的queue裡進行消息同步。

好處

任何一個機器當機了,沒事兒,别的機器都可以用

壞處

  • 性能開銷太大

    消息同步所有機器,導緻網絡帶寬壓力和消耗很重!

  • 沒有擴充性

    如果某個queue負載很重,你加機器,新增的機器也包含了這個queue的所有資料,并沒有辦法線性擴充你的queue

RabbitMQ有很好的管理控制台,就是在背景新增一個政策,這個政策是鏡像叢集模式的政策,指定的時候可以要求資料同步到所有節點的,也可以要求就同步到指定數量的節點,然後你再次建立queue的時候,應用這個政策,就會自動将資料同步到其他的節點。

大廠原來都是這樣實作分布式消息隊列的高可用RabbitMQ 高可用kafka的高可用性

kafka的高可用性

多個broker組成,每個broker是一個節點

建立一個topic,這個topic可劃分為多個partition,每個partition可以存在于不同的broker上,每個partition就放一部分資料。

這就是天然的分布式MQ, 即一個topic的資料,分放在多個機器,每個機器就放一部分資料。

RabbitMQ之類并非分布式MQ,他就是傳統MQ,隻不過提供了一些叢集、HA機制。因為無論怎麼玩,RabbitMQ一個queue的資料都是放在一個節點裡的,鏡像叢集下,也是每個節點都放這個queue的完整資料。

kafka 0.8以前,沒有HA機制,任一broker當機了,那個broker上的partition就廢了,沒法寫也沒法讀,無高可用性。

kafka 0.8以後,提供了HA機制,就是replica副本機制

  • 每個partition的資料都會同步到其他機器,形成自己的多個replica副本
  • 然後所有replica會選舉一個leader出來,那麼生産和消費都跟這個leader打交道
  • 其他replica就是follower

如此一來

  • 寫的時候,leader會負責把資料同步到所有follower上去
  • 讀的時候就直接讀leader上資料即可

隻能讀寫leader?

要是你可以随意讀寫每個follower,那麼就要關心資料一緻性,系統複雜度太高,很容易出問題。

kafka會均勻的将一個partition的所有replica分布在不同的機器上,這才可提高容錯性。

這麼搞,就有所謂的高可用性:

因為若某個broker當機了,沒事兒,那個broker上面的partition在其他機器上都有副本,若這上面有某個partition的leader,則此時會重新選舉一個leader,大家繼續讀寫那個新的leader即可。

寫資料時,生産者就寫leader,然後leader将資料落地寫本地磁盤,接着其他follower自己主動從leader來pull資料。一旦所有follower同步好資料了,就會發送ack給leader,leader收到所有follower的ack之後,就會傳回寫成功的消息給生産者。(當然,這隻是其中一種模式,還可适當調整這個行為)

消費時,隻會從leader去讀,但隻有一個消息已被所有follower都同步成功傳回ack時,這個消息才會被消費者讀到。

大廠原來都是這樣實作分布式消息隊列的高可用RabbitMQ 高可用kafka的高可用性