消息中間件:消息隊列(Message Queue)解讀

什麼是消息隊列呢?

解讀一下:隊列,應該都知道,一種先進先出的數據結構。

那什麼是消息隊列呢?可以簡單理解爲:當有大批的數據請求處理的時候,我們作爲管理人員,必須保證整個處理業務的有序進行,且還要保證每個數據都能正常處理。

那麼我們開發人員就要制定一套處理機制:“排隊,先來的先處理”。

生產服務器不斷的往MQ中放進去數據,那麼消費服務器就需要不斷的從MQ中取出數據進行處理。

 

那麼消息隊列的常見的業務場景有哪些呢?

我們可以從業務痛點來進行說明,在分佈式應用中,很多服務之間都是相互調用的,很有可能一個業務邏輯我們需要使用到多個服務,那麼我作爲當前業務的主服務器,我需要對其他幾個服務發送數據,那麼我還需要進行對這幾個服務的監控,需要考慮多方因素導致的消息發送失敗,然後對其發送失敗是否需要考慮失敗處理措施...等等等。倘若這時候,又一個新的服務加進這個業務邏輯中,也需要這個消息,那麼我主服務還需要對代碼邏輯的修改,來將新服務也給發送一份消息,倘若又有一個?又有N個呢?

這肯定是不行的,程序猿會掉頭髮了,天天改代碼,改一些毫無意義的代碼。

那麼這個時候就需要一種編程思想的處理:解耦

那麼具體的處理方案就是使用:消息隊列來進行解耦了。

具體方案如下:

第一步,我們可以使用一個消息隊列放在主服務和其他消費服務中間,我主服務將斷絕與其他服務的直接關係。我主服務作爲一名生產者,只需要將我需要發送的消息,挨個放到消息隊列服務中,然後就不管了,至於哪些消費者需要這些消息,你們自己去消息隊列中取就是了。這樣就對服務間的耦合性降低,從而解耦。但是此處會有一個弊端:如果某個消費者服務沒有取到數據,造成了數據丟失,那麼我生產者服務是完全不知曉的,也沒有辦法進行重發的。這也需要另外一些服務方案進行處理了。

對於爲了解耦,使用消息隊列的業務場景在我們實際的開發中屢見不鮮,很多,在本人開發的項目中,有一個場景很能代表,就是檢測服務,和算法服務。檢測服務負責將硬件領域檢測到的數據收集,將其放到消息隊列中去,然後算法服務不斷的發現隊列中存在需要分析的數據,不斷的取出數據,然後分析完成會放到緩存和DB中,檢測服務發現緩存中存在該體檢的分析後數據了,那麼將反饋給用戶。當然消息隊列的弊端也體現出來了,由於某些大型的活動,再加上體檢高峯期,消費者跟不上生產者的步伐,導致體檢數據大量堆積在消息隊列中,算法服務器分析不過來的時候,只能挨個正常速度慢悠悠分析,然後生產者那邊又不知道什麼情況,只能以爲算法服務器殆機了,作爲用戶的角度認爲,你這個系統不行,沒有用。那麼這個時候,我們需要做一些應急處理措施,提醒措施,目前我們採用的是一種消息隊列超過5條就立即應急預警。然後採用異步線程方式給用戶延遲處理數據。這也是我們接下來要說的另外一個消息隊列的核心特點了:異步。

 

異步

異步這個機制,必須要用的,這樣想想,作爲一個主服務,我還需要考慮其他服務都解決了,並且反饋了結果之後我纔給用戶進行響應,這這這,這樣寫代碼,在古代是要被活活打死的。

你這樣想想,我主服務接收到用戶的請求5ms,主服務把數據進行IO操作200ms,然後發送給服務A,它又進行IO操作300ms,然後我又把數據發送給服務B,它又進行了IO操作200ms,然後我又把數據發送給了服務C,它也不厭其煩的進行了一些IO操作...你想想,主服務是不是無語了??,這樣如果單線程的走,那麼是不是用戶那邊收到請求需要5+200+300+200=··ms,這用戶體驗來說,太差了,作爲開發者來說,要讓用戶無感操作。且整個處理流程,一般來說,必須保證在200ms以內。

那麼我們如果使用消息隊列,那麼我主服務直接將消息放到MQ中,耗時3ms,然後響應用戶,那麼就只是3+5=8ms,對於用戶角度來說,就是一個靜態網頁嘛。至於服務ABC分別在對應他們的消息隊列中取數據,那你自己開線程跑就是了。好了之後,我後面取數據就是了。

 

削峯

這個問題,在解耦的實際案例中說到了,就是請求服務,在該來的時候不來,要麼不來,要麼一下全來了

如果是普通處理方案,用戶突然一下發起了8k+的請求,這這這,我算法服務器閒時閒,忙時忙死啊。

一般的MySQL執行操作,頂多支撐每秒2k+就是很厲害了。如果直接搞到每秒8k+,那麼mysql將直接死掉。那麼如果一般時間來說,在下午的時候,1w的用戶在線上同時操作,頂天每秒50個請求,那這個對於整個系統來說,就是小兒科了。但是這種情況只是理想狀態。

 

那麼我們使用MQ的好處呢?

如果使用消息隊列,每秒8k+個請求寫入,那麼算法服務器每秒最多處理2k個,那麼算法服務器就一個2k,一個2k的拉取,一個個處理,這樣,即使是高峯期,也不會把服務器搞崩掉,但是此處會有一個大問題,就是如果在中文高峯期的時候,那可能就會有幾百萬,幾千萬的消息積壓在隊列中,這個時候,算法服務器還是慢悠悠的2k,2k,2k。。。。急死人。那麼我們就需要考慮其他高可用的方案了,比如再開幾臺算法服務器等方案。當然,平攤一下,相對於吧高峯期的隊列請求給平攤到後面的部分時段。這也是“削峯”的一個概念。

 

 

好處如上,那麼消息隊列有什麼弊端呢?

其實在上面的時候,已經說明了,總結來說:

1.系統的可用性降低(整個業務邏輯,全部依賴於消息隊列,如果消息隊列一掛,整個系統就崩了)

2.系統複雜度提高(萬一消息丟失咋辦?萬一重複消費?)

3.一致性問題(萬一消費者A消費了?BCD分神了呢?這樣不就順序性掉了嗎?)

 

總結來說

所以說消息隊列是一種複雜的中間件技術架構,這也和很多的架構技術的特性類似,使用這類提升開發效率,系統運行效率的技術,同時也會帶來一定的維護成本,類似分佈式,服務的分離確實加大了業務的處理的專一性,但是無疑也加大了系統的維護性。

 

關於中間件有什麼技術實現:(拷貝而來)

Kafka、ActiveMQ、RabbitMQ、RocketMQ 有什麼優缺點?

特性 ActiveMQ RabbitMQ RocketMQ Kafka
單機吞吐量 萬級,比 RocketMQ、Kafka 低一個數量級 同 ActiveMQ 10 萬級,支撐高吞吐 10 萬級,高吞吐,一般配合大數據類的系統來進行實時數據計算、日誌採集等場景
topic 數量對吞吐量的影響     topic 可以達到幾百/幾千的級別,吞吐量會有較小幅度的下降,這是 RocketMQ 的一大優勢,在同等機器下,可以支撐大量的 topic topic 從幾十到幾百個時候,吞吐量會大幅度下降,在同等機器下,Kafka 儘量保證 topic 數量不要過多,如果要支撐大規模的 topic,需要增加更多的機器資源
時效性 ms 級 微秒級,這是 RabbitMQ 的一大特點,延遲最低 ms 級 延遲在 ms 級以內
可用性 高,基於主從架構實現高可用 同 ActiveMQ 非常高,分佈式架構 非常高,分佈式,一個數據多個副本,少數機器宕機,不會丟失數據,不會導致不可用
消息可靠性 有較低的概率丟失數據 基本不丟 經過參數優化配置,可以做到 0 丟失 同 RocketMQ
功能支持 MQ 領域的功能極其完備 基於 erlang 開發,併發能力很強,性能極好,延時很低 MQ 功能較爲完善,還是分佈式的,擴展性好 功能較爲簡單,主要支持簡單的 MQ 功能,在大數據領域的實時計算以及日誌採集被大規模使用

綜上,各種對比之後,有如下建議:

一般的業務系統要引入 MQ,最早大家都用 ActiveMQ,但是現在確實大家用的不多了,沒經過大規模吞吐量場景的驗證,社區也不是很活躍,所以大家還是算了吧,我個人不推薦用這個了;

後來大家開始用 RabbitMQ,但是確實 erlang 語言阻止了大量的 Java 工程師去深入研究和掌控它,對公司而言,幾乎處於不可控的狀態,但是確實人家是開源的,比較穩定的支持,活躍度也高;

不過現在確實越來越多的公司,會去用 RocketMQ,確實很不錯(阿里出品),但社區可能有突然黃掉的風險,對自己公司技術實力有絕對自信的,推薦用 RocketMQ,否則回去老老實實用 RabbitMQ 吧,人家有活躍的開源社區,絕對不會黃。

所以中小型公司,技術實力較爲一般,技術挑戰不是特別高,用 RabbitMQ 是不錯的選擇;大型公司,基礎架構研發實力較強,用 RocketMQ 是很好的選擇。如果是大數據領域的實時計算、日誌採集等場景,用 Kafka 是業內標準的,絕對沒問題,社區活躍度很高,絕對不會黃,何況幾乎是全世界這個領域的事實性規範。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章