爲什麼需要消息隊列,消息隊列主要解決的是什麼問題?

消息隊列是最古老的中間件之一,從系統之間有通信需求開始,就自然產生了消息隊列。但是給消息隊列下一個準確的定義卻不太容易。我們知道,消息隊列的主要功能就是收發消息,但是它的作用不僅僅只是解決應用之間的通信問題這麼簡單。

經驗所得,我總結了一下幾點,哪些問題適合使用消息隊列來解決?該篇文章會記錄一下日常開發中,哪些問題適合使用消息丟列解決。

1、異步處理

以“秒殺系統”爲慄,秒殺系統需要解決的核心問題是,如何利用有限的服務器資源,儘可能多地處理短時間內的海量請求,我們知道,處理一個秒殺請求包含了很多步驟,例如:

風險控制 -> 庫存鎖定 -> 生成訂單 -> 短信通知 -> 更新統計數據 ,如果沒有任何優化,正常的處理流程是:App 將請求發送給網關,依次調用上述 5 個流程,然後將結果返回給 APP。對於對於這 5 個步驟來說,能否決定秒殺成功,實際上只有風險控制和庫存鎖定這 2 個步驟。只要用戶的秒殺請求通過風險控制,並在服務端完成庫存鎖定,就可以給用戶返回秒殺結果了,對於後續的生成訂單、短信通知和更新統計數據等步驟,並不一定要在秒殺請求中處理完成。

處理一個秒殺請求,從 5 個步驟減少爲 2 個步驟,這樣不僅響應速度更快,並且在秒殺期間,我們可以把大量的服務器資源用來處理秒殺請求。秒殺結束後再把資源用於處理後面的步驟,充分利用有限的服務器資源處理更多的秒殺請求,可以看到,在這個場景中,消息隊列被用於實現服務的異步處理,這樣做的好處是:

可以更快地返回結果;減少等待,自然實現了步驟之間的併發,提升系統總體的性能。

2、流量控制

同樣說“秒殺系統“,我們已經使用消息隊列實現了部分工作的異步處理,但我們還面臨一個問題:如何避免過多的請求壓垮我們的秒殺系統?

一個設計健壯的程序有自我保護的能力,也就是說,它應該可以在海量的請求下,還能在自身能力範圍內儘可能多地處理請求,拒絕處理不了的請求並且保證自身運行正常。不幸的是,現實中很多程序並沒有那麼“健壯”,而直接拒絕請求返回錯誤對於用戶來說也是不怎麼好的體驗。

因此,我們需要設計一套足夠健壯的架構來將後端的服務保護起來。我們的設計思路是,使用消息隊列隔離網關和後端服務,以達到流量控制和保護後端服務的目的。加入消息隊列後,整個秒殺流程變爲:
1. 網關在收到請求後,將請求放入請求消息隊列;
2. 後端服務從請求消息隊列中獲取 APP 請求,完成後續秒殺處理過程,然後返回結果;

秒殺開始後,當短時間內大量的秒殺請求到達網關時,不會直接衝擊到後端的秒殺服務,而是先堆積在消息隊列中,後端服務按照自己的最大處理能力,從消息隊列中消費請求進行處理。

這種設計的優點是:能根據下游的處理能力自動調節流量,達到“削峯填谷”的作用。但這樣做同樣是有代價的:

1.增加了系統調用鏈環節,導致總體的響應時延變長;
2.上下游系統都要將同步調用改爲異步消息,增加了系統的複雜度

那還有沒有更簡單一點兒的流量控制方法呢?如果我們能預估出秒殺服務的處理能力,就可以用消息隊列實現一個令牌桶,更簡單地進行流量控制。

其實令牌桶控制流量的原理是:單位時間內只發放固定數量的令牌到令牌桶中,規定服務在處理請求之前必須先從令牌桶中拿出一個令牌,如果令牌桶中沒有令牌,則拒絕請求。這樣就保證單位時間內,能處理的請求不超過發放令牌的數量,起到了流量控制的作用。

實現的方式也很簡單,不需要破壞原有的調用鏈,只要網關在處理 APP 請求時增加一個獲取令牌的邏輯。

3、服務解耦

消息隊列的另外一個作用,就是實現系統應用之間的解耦。再舉一個電商的例子來說明解耦的作用和必要性。

我們知道訂單是電商系統中比較核心的數據,當一個新訂單創建時:

  1.  支付系統需要發起支付流程;
  2.  風控系統需要審覈訂單的合法性;
  3.  客服系統需要給用戶發短信告知用戶;
  4.  經營分析系統需要更新統計數據;
  5.  ……

這些訂單下游的系統都需要實時獲得訂單數據。隨着業務不斷髮展,這些訂單下游系統不斷的增加,不斷變化,並且每個系統可能只需要訂單數據的一個子集,負責訂單服務的開發團隊不得不花費很大的精力,應對不斷增加變化的下游系統,不停地修改調試訂單系統與這些下游系統的接口。任何一個下游系統接口變更,都需要訂單模塊重新進行一次上線,對於一個電商的核心服務來說,這幾乎是不可接受的。

所有的電商都選擇用消息隊列來解決類似的系統耦合過於緊密的問題。引入消息隊列後,訂單服務在訂單變化時發一條消息到消息隊列的一個主題 Order 中,所有下游系統都訂閱主題 Order,這樣每個下游系統都可以獲得一份實時完整的訂單數據。無論增加、減少下游系統或是下游系統需求如何變化,訂單服務都無需做任何更改,實現了訂單服務與下游服務的解耦

心得總結

以上就是消息隊列最常被使用的三種場景:異步處理、流量控制和服務解耦,當然,消息隊列的適用範圍不僅僅侷限於這些場景,還有包括:

  • 作爲發佈 / 訂閱系統實現一個微服務級系統間的觀察者模式;
  • 連接流計算任務和數據;
  • 用於將消息廣播給大量接收者...

同時我們也要認識到,消息隊列也有它自身的一些問題和侷限性,包括:

  • 引入消息隊列帶來的延遲問題;
  • 增加了系統的複雜度;
  • 可能產生數據不一致的問題。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章