背景
RabbitMQ現在用的也比較多,但是沒有過去那么多啦,現在很多的流行或者常用技識訓者思路都是從過去的思路中演變而來的,了解一些過去的技術,對有些人來說可能會產生眾里尋他千百度的頓悟,加深對技術的理解,更好的應用于作業中去,
本篇整體采用從淺到深的邏輯結構來描述,
入門部分
什么是MQ
MQ全稱是Message Queue,訊息的佇列,因為是佇列,所以遵循FIFO先進先出原則,因為存放的是訊息,所以是一種跨行程的通信機制,
為什么使用MQ
流量削峰
這個跟很火的小吃店門口的排隊原理是一樣的,實時呼叫就好像是大家蜂擁而至,如果系統處理能力不夠,就會讓店家手忙腳亂,說不定會在冰激凌上澆上可樂,排隊能保證有條不紊,代價是整體處理速度會慢些,
異步處理
當A呼叫B,B可能要花很長一段時間來完成,這時候一般有三種方式來異步處理,A呼叫B,B回傳A說收到呼叫請求了,同步請求已經完成,但B的執行才剛開始,這時候,第一種方式是A每隔一段時間來查詢一次,看B是否執行完,這是拉的方式;第二種方式是A提供一個回呼地址,B執行完之后回呼A,這是推的方式;第三種就是使用MQ,A使用MQ給B發訊息,B處理完再回一個訊息,好處是上面提到的同時可以流量削峰,
應用解耦
MQ實作了邏輯解耦+物理解耦,邏輯上,將請求和結果處理分開了;物理上,系統只用與MQ通信,聽起來,MQ要優雅很多,但是上面提到異步處理的三種方式的前兩種,現在也多很常見,那是因為MQ是有代價的,那就是需要一套MQ設施,做開放平臺,用戶之間的唯一設施就是互聯網,這時候更依賴雙方的協議約定,所以前兩種異步處理方式不會被MQ取代,
MQ的分類
ActiveMQ是早期的MQ,倚老賣老一下,我那個年代用過,目前優勢已經不太明顯了,
Kafka號稱是大資料的殺手锏,以百萬級TPS吞吐量名聲大噪,時效是ms級別,分布式的可用性高,消費者采用拉的方式獲取訊息,訊息有序,通過控制可以保證訊息僅被消費一次,但是單機超過64個磁區,load會明顯飆高;實時性取決于輪詢時間間隔,關鍵是有可能丟訊息,不適合訂單業務中使用,
RocketMQ是國貨,用Java語言實作,在設計時參考了Kafka,單機吞吐量達到十萬級別,分布式架構可用性高,訊息可以0丟失,擴展性高,但是支持的客戶端成熟的也就是Java,核心代碼沒有實作JMS,遷移需要修改大量代碼,
RabbitMQ是erlang開發的,吞吐量達到萬級別,穩定、健壯、跨平臺,支持多種語言,企業間通信中常用,
JMS支持
RabbitMQ不支持JMS協議,這個很好理解,因為JMS是Java訊息服務,提供了訊息傳遞的Java標準API,而RabbitMQ是Erlang寫的,對Java的支持會弱一些,但是RabiitMQ實作了AMQP標準協議,AMQP只是統一了資料交換的標準格式,與語言無關,
核心部分
核心概念
所有的MQ都由生產者、消費者和broker(佇列)三部分組成,但是不同的實作,根據核心思想不同,內部結構也各有特色,
比如銀行系統中常用的跨銀行間通信的MQ,相當于兩組MQ拼起來的,
普通MQ

跨企業MQ

這樣做的好處是任何一端網路出現問題,都可以暫存訊息,等待網路恢復,不丟失訊息,訊息的重試放在broker端,減少了應用端的復雜度,為什么這里舉例時提到銀行間使用呢,因為使用這種模式的MQ,最重要的是有錢,因為想達到理想效果,要拉專線,并使用高配機器,
RabbitMQ和Kafka是一樣的
再回來考慮普通MQ的場景,如果這個MQ是RabbitMQ,組件細化一下是這樣:

這張圖上來看,其實RabbitMQ和Kafka是一樣的,來看Kafka的:

表面上來看,RabbitMQ的服務器(Broker)端由Exchange和Queue兩部分組成,Exchange是交換機,交換機是做路由的,Kafka生產者發到Broker也需要路由啊,來決定路由到哪個Partition(也就是佇列)中去,只不過Kafka的路由模式很固定,就是先找到哪個topic,然后使用負載均衡的策略找到一個Partition來投遞訊息,Kafka是用了邏輯概念topic簡化了exchange路由,所以Kafka的路由功能也很單一,
表面上,RabbitMQ的生產者和消費者與服務端都是Channel信道來相連,Channel是復用連接來進行通信的,Kafka也是需要的,只是它內部幫我們把這些與核心功能關系不大的都自己內置實作了,而RabbitMQ暴露給用戶,提供了更高的靈活性,
上面的兩段如果我沒有講明白,也沒有關系,只要知道更年輕的Kafka沒有Exchange和Channel的概念是類似于采取了約定大于配置的方式提供的服務,
核心功能
RabbitMQ的核心實際上就是AMQP的核心:MessageQueue、Exchange和Binding,
MessageQueue就是訊息佇列,一個佇列里的一條訊息,也就是同一個message ID對應的訊息,不管有多少個消費者來分攤壓力,也只能被消費一次,訊息佇列和消費者之間有ack機制,訊息一旦確認安全送達,RabbitMQ服務端就可以安全洗掉訊息了,
Binding是MessageQueue與Exchange之間的連接,Exchange只能給Binding的MessageQueue發送訊息,
Exchange有四種型別:fanout、topic、direct和header,本質上就是有一堆MessageQueue,一個訊息是要被復制幾份,發到哪幾個Binding的訊息佇列去,Exchange給定了規則:fanout是對每個訊息佇列復制一份發送;direct意思是只發指定的一份,不復制;topic是發送通配符匹配的幾份;header可以指定一些其他的過濾條件發送,訊息從生產者發送到exchange之后也有ack機制來保證訊息的可靠傳輸,
Kafka只有topic的概念,這是因為Kafka的設計上訊息只用存一份,通過游標,發送后不立即洗掉訊息,多個消費者組可以互不影響的消費,這是Kafka的一大改進,
內部原理
大家面試時有沒有被問過:Kafka怎么保證訊息能且僅能收到一次?這是個埋坑題,是與面試官斗智斗勇的開始,什么冪等、事務、流式EOS呀,其實呢,Kafka本身是不保證僅且僅收到一次的,所以這些實作方法都不優雅,
RabbitMQ通過AMQP事務機制,還有上面已經提過的ack也就是confirm兩種可選方式保證訊息被收到,
但是最為優雅的實作是IBM的Websphere MQ,因為這是收費的,所以研究的人不多,它通過訊息序列號保證訊息不丟失、不重傳,
通道為每條訊息的傳送分配一個序列號,它會自動累積增值,訊息序列號由發送通道分配,是通道的一個永久屬性,每當發送一條訊息,訊息序列號就加一,通道的相關屬性SEQWRAP標識序號的最大值,預設為999,999,999,序列號越界后自動歸零,從頭開始,
正常情況下,通道兩端的訊息序列號或者相等或相差為一,雙方對前面的某一潭訓一批訊息是否發送成功理解不一致,在解決了不確定的訊息后,可以用MQSC命令通過重置訊息序號將雙方調整到一致,一旦連接斷開后,通道重連時雙方會將訊息序號同步,
推薦閱讀
常用邏輯結構
實戰并發-使用分布式快取和有限狀態機
應用角度看kafka的術語和功能
穩定性五件套-限流的原理和實作
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/338970.html
標籤:架構設計
上一篇:UML 活動圖
下一篇:RabbitMQ設計原理決議
