概述
訊息佇列(Message Queue),是分散式系統中重要的元件,是一種程式間通訊或者是同一程式的不同執行緒的通訊方式。和 http 同步協議不同的是,訊息佇列是一種非同步的通訊協議,不需要立即獲得結果。
訊息佇列的使用場景
- 非同步處理
- 流量控制
- 應用解耦
應用解耦
訊息佇列的一個作用就是實現系統應用之間的解耦。舉例一下電商系統的中的訂單系統。
當建立一個訂單時:
- 發起支付
- 扣減庫存
- 發訊息告知使用者
- 更新統計資料
這些訂單下游的系統都需要實時獲得訂單資料,隨著業務量的增大和業務的變更,有一段時間不需要發訊息給客戶,或者需要新增功能,每次都需要不斷的調式訂單系統和下游系統。
引入訊息佇列後,訂單服務在建立訂單時傳送一條資訊到訊息佇列主題 Order 中,所有的下游都訂閱主題Order,這樣無論增加、減少下游系統還是下游系統的功能如何變化,訂單服務都不需要做更改了,實現了訂單服務和下游服務的解耦。
非同步處理
非同步處理是將很多序列進行的步驟轉成非同步處理,還是已訂單系統為例,下單訂單需要建立訂單和鎖定庫存,確定本次請求後馬上給使用者返回響應,然後把後續請求的資料的都在訊息佇列,由訊息佇列非同步處理。
這樣把五個步驟減少為兩個步驟,假設每個步驟處理時間需要500ms,在不考慮網路延遲的情況下:
序列處理: 500 * 5 = 2500ms
並行處理:500 * 2 = 1000ms
系統響應時間縮短一半以上。這樣響應速度更快,而且把請求放在後續操作,可以充分利用更多的資源處理請求。
所以我們可以看到,實現非同步操作的服務:
- 更快地返回結果
- 減少等待時間,提升系統總體效能
流量控制
在購物網站的做一個秒殺活動,平時網站能支撐每秒1000次併發請求,但是電商秒殺一下請求猛增到每秒3000次請求,多出來的請求,可能直接讓系統當機。
所以我們就需要使用訊息佇列來控制流量,當系統短時間接收到大量請求時,會先將請求堆積到訊息佇列上,後端服務從訊息佇列上消費資料,訊息佇列相對於給後端服務做了一次緩衝。
優缺點
上面的概述總結起來有個三個優點:非同步、削峰和解耦。
缺點有以下幾個:
- 系統可用性降低
- 增加系統複雜度
- 可能會資料一致性問題,比如資料丟失,資料重複傳輸
RabbitMQ訊息佇列五種工作模式
在rabbitmq官網教程上介紹了幾種工作模式,
簡單(simple)模式
The simplest thing that does something
從上面的示意圖看出來 simple 模式有以下幾個特徵:
- 只有一個生產者、一個消費者和一個佇列
- 生產者和消費者在傳送和接收訊息時,只需要指定佇列名稱,而不需要傳送那個 Exchange 交換機。
工作(Work)模式
在多個消費者之間分配任務(競爭消費者模式)
建立一個工作佇列,新增多個消費者共同消費工作佇列上的任務。每一個訊息都給一個消費者消費
釋出訂閱(Publish/Subscribe)模式
工作模式中每個訊息只能被一個消費者消費,釋出訂閱模式是每個訊息同時給多個消費者消費。
上圖中的X
表示Exchange
交換器,Exchange
型別有:Direct、Topic、Headers和Fanout。
- 釋出訂閱用的是 Fanout
- Fanout 是不需要指定具體的佇列名,Exchange 會將訊息轉發所有的繫結的佇列
路由(Routing)模式
路由模式中的交換器型別為 direct,在同一個交換器,由生產者指定指定目標佇列。
- 指定規則按照 RoutingKey 指定
- 消費者通過 BindingKey 繫結自己接收訊息佇列
- 只有 RoutingKey 和 BindingKey 匹配佇列才會收到資訊
RoutingKey 是生產者指定 Exchange 路由到哪個佇列,BindingKey 用於消費者繫結到某個佇列
主題(Topic)模式
主題模式是根據萬用字元繫結佇列,其中 * 可以替換任務一個識別符號,# 可以替換多個識別符號,萬用字元和名稱使用 . 隔開。
- 主題模式的 Exchange 型別為 topic
- 每個訊息可以被多個佇列消費