①消息隊列的優缺點
優點:異步解耦和削峰
缺點:系統引入mq之后可能存在的一些問題
1系統可用性降低(mq出問題 整個系統就掛了 多了一道環節)
2 系統變復雜 考慮的問題變多(如果系統和mq協調出現問題 往里面加了兩條一樣的數據 或 是消息積壓 或是丟消息 )
3 一致性的問題:a系統給bcd都執行成功才返回結果 結果abc都成功了 d出問題了 導致整個請求給用戶返回成功 但是還有部分邏輯沒處理成功
②activemq rabbitmq,rocketmq kafka,各種優缺點
萬級 萬級 10萬 10萬 (單機吞吐量)
ms 微s ms ms(延時 生產 和消費時間)
會丟 0丟失 0丟失(消息丟失情況)
activemq 底層是java寫的,比較成熟但是不適合吞吐量大的場景 且社區更新慢
rabbitmq 性能好,mq功能比較完善,管理界面好用 但是是erlang 語言寫的 天生的並發能力好 性能強 延時低(適合中小公司)社區活躍
rocketmq topic達到幾百個 消息0丟失,分布式架構 擴展起來方便 阿里開源的 java開發的(團隊項目解散 這個項目就黃了,更新維護就沒了)
kafka 單機吞吐10萬甚至百萬 但是 topic 多的話吞吐量下降 功能簡單 大數據計算 上 數據采集 日志 吞吐量高 拓展性高
③如何保證 消息隊列的高可用
rabiitmq的高可用:
普通集群模式分析:從一台去消費數據如果不在 就去其他節點上找數據
缺點1:可能會在rabbitmq會出現大量的數據傳輸
缺點2 : 可用性幾乎不存在任何保證 如果節點掛掉 找不到數據了
鏡像集群模式:(在管控台上可以設置這個模式 設置節點上數據是不是要同步到其他隊列上)
每一個節點都會將數據進行同步到其他節點上去:(每一個節點都有這個隊列的完整鏡像,全部數據) 消費的時候 任何一個節點消費都行
kafka的高可用怎么設計:
每台機器上啟動一個進程broker進程(集群中的節點)
創建一個topic,指定其partition的數量多個,表明數據存在多台服務器的多個patition上.0.8版本前沒有高可用機制的.
如果一台服務器宕機,數據就會丟失,0.8以后,每個patition都有一個副本,通過replica副本機制來實現的
選舉為leader其他的副本就是follower 生產者只能往leder里面寫數據 消費者也只能從leader里面消費數據
如果leder死掉了 follower中選出一個leader
④為什么會消費到重復的消費?保證消息的冪等性.
kafka 每條消息中都存在一個offset 代表這個消息順序的序號)
消費者消費之后回去提交offeset 表示已經消費該數據 zookeeperr記錄消費者當前消費到了offset那幾條數據
如果消費者重啟 只需要將沒有消費的數據發送過來.
消費者並不是消費完一條數據就立馬提交offset 而是定期提交一次offset,在提交之前消費者重啟 系統就不知道你消費了沒有
冪等性的保障機制
如果重復數據,每次消費一次 數據庫中存一次 然后redis中存一下存在這個消息記錄 那就不要再插入了
⑤怎么保證消息的可靠性?(怎么保證消息不丟失)一般是confirm機制 異步的,不會阻塞 吞吐量會大一些
生產者 ----> rabbiitmq------->消費者
1 寫消息網絡傳輸中消息丟失,mq中沒保存下來
2 在mq中暫存於內存中,還沒消費 mq掛了 消息丟失
3 消費者消費消息 還沒處理就自己掛掉了,但是rabbitmq以為消費者已經處理完了
rabbitmq中的事務 (同步的生產者發送消息的吞吐量下降) 通過try catch 發送消息,出現異常,catch到之后回滾,重試發送消息成功就提交
① 將channal設置成confirm的模式 ②發送消息 ③然后就不用管了 ④ 如果rabbitmq接收到這條消息,會回調本地的接口 說這條消息已經接收到了 ⑤如果報錯 回調接口接受失敗 可以再次重發
持久化到磁盤中,創建queue時候就持久化
原因:自動ack但是沒處理完就ack 此時宕機 數據丟失
處理辦法 :消費者autoack機制 關閉 在處理完消息之后,手動的ack 如果在消息沒處理完 rabbitmq會將消息給其他的消費者來處理.
kafka數據丟失:
唯一數據丟失的情況就是 消費到這個消息 自動提交offset 讓kafka確保消費導數據再提交offset
數據在存到leader時候 還沒來的及將數據發送到follower上.此時leader宕機 數據會丟失
每個patition至少兩個副本,至少保證有一個follower和leader有聯系 生產者必須acks=all 消息寫入所有的副本中 才認為消息寫入成功 如果失敗的話 無限重試 .
⑥消息隊列中保證消息的順序進行
比如在主從同步 biglog mysql-->mysql 這個肯定要按順序來進行操作
rabbitmq中:
保證數據消費的數據放在一個隊列中 只讓一個消費者消費 就能保證其數據結構的順序進行
kafka中:
一個消費者就消費一個patition 如果消費者中間存在多個線程去進行處理的話 消息會錯亂的
(4核8g 開 32個線程 每秒1000多個)
內存隊列 中也是有順序的 + 多線程 來處理 每個線程處理也是有順序的
⑦不是分布式的mq 如果數據量很大 數據產生積壓 無法容納所有數據怎么辦呢?
實際開發中就是讓消費者故障,只能讓消費者重新消費 緊急擴容.將3個patition中取出的數據 在放到30個patition 中去進行 操作 時間就可以縮短為原來十倍
mq延時過期怎么處理 ,設置過期之后消息會自動刪除 生產中一般都不會用的
只能手動去查出來 然后重新導入mq中
如果是磁盤滿了 怎么辦 呢 只能寫個臨時程序 讓消費者快速消費
⑧如果自己設計一個消息中間件(mq的架構)
mq支持擴容 分布式 參考kafka架構 每個機器房部分數據 順序寫 持久化到磁盤 多副本的保障機制