MQ思考&總結
為什麼我們要用MQ? 最關鍵點我認為是解耦,這樣各系統間不用有太多的相互依賴,按需消費即可。再者是非同步,提高服務效能。然後就是削峰,防止過多流量湧入而給伺服器帶來壓力。
那用MQ會有哪些問題呢?我們呼叫介面的話基本就是呼叫成功或超時重試再不行打個日誌,那MQ呢,首先屬於中介軟體產品,它本身的可用性有沒有保證?如何保證的?發的訊息可能丟失嗎?會不會延遲?重複發?到達的訊息能按順序嗎?如果都可以的話,該怎麼選擇適合自己的MQ呢,運維成本怎麼樣?...都可以反問自己。
MQ會不會丟訊息呢?這點可以想下哪些鏈路可能導致訊息丟失呢,無非是三點:呼叫方到MQ的過程丟了 ;MQ本身重啟了;MQ到消費方過程丟了。其實都是有辦法避免的,MQ本身有確認機制,比如我們配置當MQ收到訊息並持久化成功後再返回呼叫方一個ack,這樣就能保證1,2點正常,同理,當消費方成功消費後再返回MQ一個ack,否則一直重試,這樣第3點也保證了。
MQ訊息延遲怎麼辦?也可以從為什麼延遲出發,是不是訊息太多了呢,是否需要增加消費者,是否可以先簡單記錄快速丟棄再找個時間補齊資料;
MQ訊息會不會重複發?關於這點呢,我覺得最好的做法是自己服務去保證就算重發了也不會有什麼問題,比如設定訊息id什麼的,或者一些冪等處理之類。
MQ訊息順序能保證嗎?關於這點可以根據具體的MQ來思考下,比方說kafka,它可以根據key做分片,比如某一個產品id下的始終路由到一臺消費機,這個時候如果是單執行緒是有序的,多執行緒的話其實可以再考慮根據規則弄一個記憶體佇列,這樣去保證某一個key下的訊息順序消費。其它MQ類似的去思考。如果實在不能保證,訊息可以帶上時間戳,比如評論的場景,先收到刪除,再收到新增,這個時候發現新增的時間戳大於刪除就放棄執行也是可以的。
回到很重點的一個問題,MQ如何保證高可用呢,萬一執行著突然掛了,或者磁碟壞了,那沒有消費完成的資料怎麼辦?這個又得結合具體的某一款MQ來分析了,比如kafka,這個據說天然分散式的設計是怎麼樣的:它採用劃分分片+HA副本機制來設計的,一個topic的訊息可以被劃分成多個partition,每個partition又可以放入不同的節點去,這樣達到了分散式;然後每個partition會同步資料到其它的機器,形成多副本,並選舉leader,生產消費只和leader打交道,還可以設定訊息寫入所有副本之後才表示成功,這樣是不是就搞定啦。至於RabbitMQ,這個的設計並不是分散式的,但是有普通叢集模式和映象叢集模式兩種,單機的就不說了哈,普通叢集模式:queue只會放在一臺例項,消費的時候如果拉到了其它例項,會從原queue在的例項再拉一下,這樣如果原queue的掛了,貌似就gg了;映象叢集模式:每個例項都會同步queue的全部資訊。這樣也有個問題是queue不能太大了,不能超過單例項的儲存限制。
如果是你自己設計MQ,你會怎麼設計呢?