大多數狀況下,使用消息隊列目的是::解耦、異步、削峯。redis
經過一個 MQ,Pub/Sub 發佈訂閱消息這麼一個模型,完全解耦了數據庫
經過MQ,使得同步的操做變爲異步操做,提升效率。架構
經過MQ,控制服務能夠接收到的請求數量併發
優勢就是在特殊場景下有其對應的好處,解耦、異步、削峯異步
缺點有如下幾個:分佈式
系統可用性下降性能
系統引入的外部依賴越多,越容易掛掉。須要保證消息隊列的高可用大數據
系統複雜度提升,保證消息沒有重複消費,怎麼處理消息丟失的狀況,怎麼保證消息傳遞的順序性?頭大頭大,問題一大堆,痛苦不已。優化
一致性問題spa
A 系統處理完了直接返回成功了,人都覺得你這個請求就成功了;可是問題是,要是 BCD 三個系統那裏,BD 兩個系統寫庫成功了,結果 C 系統寫庫失敗了,咋整?你這數據就不一致了。
ack(消費者確認)(消費者手動ack)
持久化 (交換機、隊列、消息)
不推薦使用消息事務,會驗證下降性能
生產者確認(publisher confirm):生產者發送消息後,等待mq的ACK,若是沒有收到或者收到失敗信息,則重試。若是收到成功消息則業務結束。
channel.waitForConfirmsOrDie(10000);
可靠消息服務(可選,本身編寫邏輯):對於部分不支持生產者確認的消息隊列,能夠發送消息前,將消息持久化到數據庫,並記錄消息狀態,後續消息發送、消費等過程都依賴於數據庫中消息狀態的判斷和修改。
經過同一個隊列多消費者監聽,實現消息的爭搶,加快消息消費速度。
答:大部分業務對消息的有序性要求不高,若是遇到對時序要求較高的業務,分兩種狀況來處理:
業務同時對併發要求不高:
保證消息發送時有序同步發送
保證消息發送被同一個隊列接收
保證一個隊列只有一個消費者,能夠有從機(待機狀態),實現高可用。
實現主從(Zookeeper集羣選主)
業務同時對併發要求較高:
知足上述第一個場景的條件
能夠有多個隊列
有時序要求的一組消息,經過hash方式分派到一個固定隊列 2 hash -> klsdilelksd
保證接口冪等便可,那麼如何保證接口冪等呢?
某些接口天生冪等,例如查詢請求
某些接口天生不冪等,好比新增,還有某些接口的修改功能
1 - 消息已接收 2- 消息正在處理 3- 已處理完畢
update set stat =3 where id =2 and stat =2
能根據具體的業務或狀態來肯定的,在消費端經過業務判斷是否執行過
msgid 轉帳的短信id=123 - 》 123456 redis msgid -> 123456,userid
特性 | 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 功能,在大數據領域的實時計算以及日誌採集被大規模使用 |
中小型公司,技術實力較爲通常,技術挑戰不是特別高,用 RabbitMQ 是不錯的選擇;
大型公司,基礎架構研發實力較強,用 RocketMQ 是很好的選擇。
若是是大數據領域