寫在前面:目前主流的MQ產品有ActiveMQ、RabbitMQ、RocketMQ、Kafka...
其適用場景很多,但是比較核心的有 3 個:解耦、非同步、削峰
解耦:毋庸置疑就是減少系統間耦合度,避免系統間相互(強)依賴(Pub/Sub釋出訂閱訊息模型)。
非同步:提高請求效率,減少響應時間,對於無事務操作依賴和資料實時性情況,可接收請求即返回使用者,將請求放入訊息佇列處理。
削峰:基於非同步特性,在特定業務場景下,解決了請求一擁而上全部湧入DB會導致DB系統崩潰問題。
訊息佇列也存在一些缺點,如下:
系統可用性降低系統複雜度提高一致性問題RabbitMQ 的高可用性基於主從(非分散式)高可用性,三種模式:單機模式、普通叢集模式、映象叢集模式。
1、單機模式
略
2、普通叢集模式
就是在多臺機器上啟動多個rabbitmq例項,每個機器啟動一個。但是你建立的queue,只會存放在一個rabbtimq例項上,但是每個例項都同步queue的元資料。實際上如果連線到了另外一個例項,那麼那個例項會從真正存有資料的queue所在例項上拉取資料過來。
沒做到所謂的分散式,就是個普通叢集。該方案主要是提高吞吐量的,就是說讓叢集中多個節點來服務某個queue的讀寫操作。
3、映象叢集模式
這種模式,才是所謂的rabbitmq的高可用模式,跟普通叢集模式不一樣的是,你建立的queue,無論元資料還是queue裡的訊息都會存在於多個例項上,然後每次你寫訊息到queue的時候,都會自動把訊息到多個例項的queue裡進行訊息同步。
Kafka的高可用由多個broker組成,每個broker就是一個節點。
建立一個topic,這個topic可以劃分為多個partition,每個partition可以存在於不同的broker上,每個partition存放放一部分資料。
kafka就是一個分散式訊息佇列,就是說一個topic的資料,是分散放在多個機器上的,每個機器就放一部分資料。
kafka 0.8以後,提供了HA機制,就是replica副本機制。每個partition的資料都會同步到其他機器上,形成自己的多個replica副本。然後所有replica會選舉一個leader出來,那麼生產和消費都跟這個leader打交道,然後其他replica就是follower。寫的時候,leader會負責把資料同步到所有follower上去,讀的時候就直接讀leader上資料即可。只能讀寫leader?很簡單,要是你可以隨意讀寫每個follower,那麼就要care資料一致性的問題,系統複雜度太高,很容易出問題。kafka會均勻地將一個partition的所有replica分佈在不同的機器上,這樣才可以提高容錯性。
kafka的這種機制,就有所謂的高可用性了,因為如果某個broker宕機了,也沒事兒,因為那個broker上面的partition在其他機器上都有副本的,那麼此時會重新選舉一個新的leader出來,大家繼續讀寫那個新的leader即可。這就有所謂的高可用性了。
所有的生產者請求和消費者請求都經過leader副本,leader副本以外的副本都是follower副本,follower副本不處理來自客戶端的請求,它們唯一的任務就是從leader副本那裡複製訊息,保持與leader副本一致的狀態。如果leader 副本發生崩潰,其中的一個follower副本會被提升為新的leader副本。
那麼符合哪些條件的follower副本才可以成為leader副本呢?答案是“同步副本”。
leader會跟蹤與其保持同步的副本列表,該列表稱為ISR(即in-sync Replica)。如果一個follower宕機,或者落後太多,leader將把它從ISR中移除。這裡所描述的“落後太多”指Follower複製的訊息落後於Leader後的條數超過預定值(該值可在server.properties中透過replica.lag.max.messages配置,其預設值是4000)或者Follower超過一定時間(該值可在server.properties中透過replica.lag.time.max.ms來配置,其預設值是10000)未向Leader傳送fetch請求。
1)寫過程
寫資料的時候,生產者就寫leader,然後leader將資料落地寫本地磁碟,接著其他follower自己主動從leader來pull資料。一旦所有follower同步好資料了,就會發送ack給leader,leader收到所有follower的ack之後,就會返回寫成功的訊息給生產者。(當然,這只是其中一種模式,還可以適當調整這個行為)
2)讀過程
消費的時候,只會從leader去讀,但是隻有當一個訊息已經被所有follower都同步成功並返回ack的時候,這個訊息才能夠被消費者讀到。
參考:https://github.com/doocs/advanced-java/blob/main/docs/high-concurrency/how-to-ensure-high-availability-of-message-queues.md
內容有參考,有自己的思考和總結,修行之路源於記錄和不斷地學習