1. 程式人生 > >rabbitmq2-這可能是最全的rabbitmq概覽了

rabbitmq2-這可能是最全的rabbitmq概覽了

在學習一個技術的時候,首先想到的應該是應用場景,然後在對比技術和技術選型的時候應該結合自己的業務,再結合每一個技術的特點進行技術的選擇,這篇博文就詳細的描述一下rabbitmq的特性

一、rabbitmq的總體模型圖

image.png

1、一些名詞解釋:
  • 生產者(P):提供訊息的一方的稱謂
  • 消費者(C):接受訊息的一方的稱謂
  • 佇列(Q):儲存訊息的一種資料結構
  • exchange (交換機|路由器):提供P到Q之間的匹配
  • routing key:當前的訊息將會被路由到那個Q中
  • binding key:聯絡Exchange和Q,Binding Key由Consumer在Binding Exchange與Message Queue時指定,而Routing Key由Producer傳送Message時指定,兩者的匹配方式由Exchange Type決定。
  • Connection:tcp連線
  • Channel:複用tcp連線的通道(埋下一個知識點,我們一會會繼續
    聊)
  • ExchangeType
    • direct :預設的模式,當routing key和binding key完全匹配的時候,才可以獲取訊息
    • topic:與上面的模式相同,但是routing key可以和binding key進行模糊匹配
    • header:忽略ExchangeType,header本來就是鍵值對結構,依據header屬性進行匹配
    • fanout:和上面一樣忽略ExchangeType的設定,把訊息廣播到它所知道的所有的佇列
2、聊聊設計思想:
  • Connection:
    看到這個東西你是不是想到了資料庫Connection,其實它們的本質都是tcp連線,你是否還想到了資料庫連線池(c3p0、druid……),其實用在這裡都是一樣的效果,有興趣你可以看看spring在整合rabbitmq的時候是如何來寫的只需要debug進去即可
  • Channel:對於一個連線來說想要保持資源的隔離和快速的通過exchange匹配到queue,這個機制是非常棒的,這麼優秀的設計思想,的確是值得我們去學習的,其實把這個點想通,然後套在多執行緒裡面也是通用的。

二、rabbitmq如何確保訊息的可靠性

這個點是我在群裡面經常被問到的問題,很多部落格也差不多是複製文件上面的下來,今天希望我能把這個問題給講解清楚。話還是回到前面當初是怎麼想到學習這個技術的呢??

1、生產者端的可靠性的保障
1.1 事務機制

image.png
是不是基本和jdbc的一致。事務的機制保障的是訊息能夠投遞出去,

1.2 confirm機制的保障:

相比於事務機制,confirm的效能要提高200倍,confirm和事務機制是互斥的,即不能同時使用
rabbitmq提供下列幾個方法來實現:
開啟channel.confirmSelect()
①同步普通模式(阻塞)waitForConfirms(),傳送一條等待服務端confirm後在傳送第二條,這實際上一種序列的模式效率不高
②同步批量模式:每傳送一批訊息之後,呼叫waitForConfirms()方法,等待服務端confirm,但假如一旦出現confirm返回false的話,那麼客戶端要將這批訊息重發會帶來重複訊息
③非同步監聽模式:confirmListener

2、消費者的保障

消費者端的訊息重試機制:
①:當消費者端掛掉了即當前的channel斷開了連線,那麼訊息會自動重回佇列,重新分發給下一個消費者
②:當前消費者拒收這個訊息,那麼rabbitmq提供引數可以使得此訊息重回佇列,那麼此條訊息便可以繼續分發給下一個消費者處理,確保這個訊息一定會有消費者去處理
以上的兩個機制便確保了訊息只要發出一定會被消費,下面我們在說如何利用這一機制來實現分散式事務。

問題: 當消費者消費完訊息,傳送應答的時候掛掉了會出現什麼情況?

這種情況會造成訊息的重複消費,A已經消費了訊息,但是應答傳送的時候網路中斷,這個時候channel已經斷開了,就需要重如佇列,下一個消費者B就會繼續消費這個訊息,就會造成訊息的重複訊息,所以在消費者端一定要有一個狀態表儲存訊息的狀態,防止被重複消費。

3、伺服器端的保障:

①:提供持久化模式,開啟這種模式即使伺服器宕機,也能在重啟的情況下保證訊息的不丟失
②:提供叢集的方式

三、rabbitmq的幾種工作模式和應用場景:

1、簡單模式:
image.png
一個生產者一個消費者一個佇列非常簡單的結構,基本上這個結構沒有什麼用
2、work模式:
image.png
一個生產一個佇列,多個消費者,每個消費者獲取的訊息唯一
3、訂閱模式:
image.png
Exchange將會把訊息投遞到所有它已知的Q,然後連線Q 的所有的C都能獲取到訊息。此時ExchangeType的模式為fanout
4、路由模式:
image.png
由routing key決定把訊息往哪個佇列裡面投遞,有binding 匹配routing key的結果來決定C是否可以獲取此Q中的訊息,這種模式下ExchangeType必須為direct
5、統配符模式:
image.png
在這種模式下可以模糊匹配

2、應用場景:

1、簡單模式:這種模式幾乎沒有什麼應用場景
2、work模式:這種應用的也比較少
3、釋出訂閱模式:這種模式適用於通知,例如通知所有的商戶週五晚上伺服器更新
4、路由模式:在叢集的環境下,我們會將一個系統的所有訊息都交由這個叢集來處理,所以所有的訊息必須要歸類,那麼這個模式就在這種情況下可以高效的處理訊息
5、統配符模式:基本和上面的類似,可以接受一類的訊息

四、訊息的公平分發:

場景:現在有兩個消費者,A的吞吐量為10,B的吞吐量為5。
在預設的模式下面,訊息佇列不管消費者是否處理完畢,都會繼續下發下一條訊息,造成的結果就是A 獲取10條訊息,B也獲取10條訊息,顯然這樣會拖慢整體的處理速度,本著能者多勞的原則。我們會盡量的讓A、B都能有一個合理的負荷來提高系統的整理的處理速度

channel.basicQos(int prefetchCount);

這個語句就會使得一次性下發prefetchCount個訊息,等待處理完成後在下發同樣的數量的訊息,這樣會提升系統的整體的吞吐量。

五、再聊分散式事務

在分散式的場景中,已經無法在做到ACID了,這個時候我們追求最終的一致性,那麼現在實現最終一致性的方法還沒有成熟的方案,據說阿里搞了一個GTS但是目前還沒有開源。本篇在這個大環境下肯定是將使用rabbitmq來實現分散式事務的最終一致性 。
- 訊息的可靠性,rabbitmq藉助於生產者端的確認機制、消費者的重試機制、伺服器端的持久化機制及叢集機制,可以確保訊息不丟失,只要訊息傳送出去就一定會被消費,如果出現大量的訊息堆積,那這個時候就可以考慮在架設快取或者增加節點了
- 訊息延遲是目前mq中最低的以微妙來計
- 藉助於消費者端的事務狀態表來保證訊息的重複消費

目前就聊到這裡,實踐出真知,下面的系列文章將會進入實戰環節。