消息隊列 解耦 A服務和多個服務耦合,內部維護對多個服務發送數據的介面,那麼這些介面如果有的掛了,有的不需要了,那麼還得修改A內部的代碼,如果使用MQ,A發送消息就好,不必考慮那麼多事情。 通過一個 MQ,Pub/Sub 發佈訂閱消息這麼一個模型,A 系統就跟其它系統徹底解耦了 非同步 不需等待整個業 ...
消息隊列
解耦
A服務和多個服務耦合,內部維護對多個服務發送數據的介面,那麼這些介面如果有的掛了,有的不需要了,那麼還得修改A內部的代碼,如果使用MQ,A發送消息就好,不必考慮那麼多事情。
通過一個 MQ,Pub/Sub 發佈訂閱消息這麼一個模型,A 系統就跟其它系統徹底解耦了
非同步
不需等待整個業務流程走完,把業務需要走的流程發送到MQ,其他服務進行消費走完接下來的流程即可
削峰
對短時間的大量請求進行隊列內的消息堆積,等待服務進行能力範圍內的消費
高可用(RabbitMQ)
三種模式:單機,普通集群,鏡像集群
單機:玩具
普通集群:多個機器,創建的隊列只會存放在一個實例上,其他實例還得拉取數據,造成了集群內部的大量流量消耗,而且隊列所在節點宕機,數據就丟了,做不到高可用,但是吞吐量會高一點
鏡像集群:創建的隊列就會存放在多個實例上,每次寫消息都會同步到所有實例 。 缺點:沒有擴展性(queue多了,加機器也沒用,因為每個機器上都有完整的數據),性能開銷大
Kafka(天然分散式)
每個機器放一部分數據,每個節點內的數據都會有副本,同步到其他機器上,然後選舉出一個leader,生產和消費都和他打交道
生產和消費都在所有的follower同步好返回ack之後消息隊列才返回操作成功
如何保證消息不被重覆消費/如何保證消息消費的冪等性
原因:kafka為例:一條消息消費後會提交offset,下一次消費會從offset後面的數據進行消費,如果消費者進程重啟,那麼消費過的offset就沒有上交,就會導致重覆消費
重覆消費不可怕,可怕的是沒考慮到重覆消費之後,怎麼保證冪等性。
生產者發送數據時,加一個全局唯一的id,消費時查一下redis是否消費過
如何保證消息的可靠性傳輸/如何處理消息丟失的問題
RabbitMQ
生產者弄丟了數據
解決方案:1. 事務機制(耗性能,因為是同步)2. confirm機制(性能號,非同步),生產者開啟confirm模式,發送的消息分配一個唯一的id,如果送達rabbitmq,會回傳一個ack消息,如果送達失敗,則會回調一個nack介面,告知接受失敗
消息隊列弄丟了數據
解決方案:消息隊列進行持久化:1. 創建隊列時進行持久化。2. 發送消息時吧參數設置為持久化
但是消息隊列還沒進行持久化就掛了咋辦:結合confirm,持久化成功之後再返回ack,如果沒有持久化那麼生產者是可以進行重發的。
消費者弄丟了數據