概要:我們使用消息隊列,就需要知道為什么要用消息隊列钱豁,什么場景需要用消息隊列,使用消息隊列能帶來哪些好處和消息隊列會帶來哪些問題疯汁?如何去避免這些問題牲尺。
一、MQ的好處
解耦:在某些場景下幌蚊,A服務訂單達到某個狀態(tài)之后谤碳,需要發(fā)生一份消息到好幾個服務,但是對于A服務來說溢豆,它并不關心其他服務如何什么時候估蹄、如何處理這個消息。那么就可以利用MQ解耦沫换。A服務只管將消息發(fā)出去,其他服務想要用這個數(shù)據(jù)最铁,就可以開啟消費者組讯赏,這樣就可以保證每個服務能消費到所有的數(shù)據(jù)了。
異步:使用異步可以提高接口響應速度冷尉,如果要跟其他系統(tǒng)交互的話漱挎,時間大概是幾百ms,而投遞到MQ時間在幾ms雀哨,而且在不同場景下調(diào)節(jié)參數(shù)可以提高消息投遞的速度磕谅。(ack的值)
削峰:在流量比較高的時候私爷,為了較少對MySQL的壓力,使用緩存主要是解決查詢的壓力膊夹,而對于寫入則可以用MQ來削峰衬浑,在高峰期時候流量進入MQ,會造成暫時的積壓放刨,等流量降低之后工秩,積壓的數(shù)據(jù)很快就會被消費完。
MQ的好處這么多进统,但是也無可避免地會帶來一些問題助币。主要是以下兩個方面1. 系統(tǒng)的可用性降低,引入了中間件螟碎,如果中間件掛了眉菱,那么數(shù)據(jù)有丟失風險2. 復雜度上升,正常的系統(tǒng)間交互掉分,我們通常不需要考慮重復消費問題俭缓,只要從HTTP請求來解決冪等性就可以。還有就是消息積壓的解決叉抡,對于MQ的監(jiān)控等問題尔崔,都要加以考慮。接下來我們就逐一看看對于常見的MQ問題褥民。
二季春、消息丟失問題
Kafka消息丟失可以分為三種情況:生產(chǎn)者發(fā)送過程丟失,Kafka丟失和消費端丟失消返。
- 生產(chǎn)者丟失:Producer端的ack表示什么情況下Kafka才認為數(shù)據(jù)成功成功發(fā)送载弄。ack=0表示生產(chǎn)者不需要等待broker的同步確認,就可以處理下一批數(shù)據(jù)了撵颊,那么如果由于網(wǎng)絡原因或者leader掛了宇攻,消息丟失了,也很難發(fā)現(xiàn)倡勇。ack=1表示生產(chǎn)者需要確認leader成功寫入就可以成功返回給生產(chǎn)者客戶端逞刷,這種配置下如果leader掛了,那么消息也會丟失妻熊。另一種比較可靠的配置是ack=-1夸浅,表示消息成功寫入leader和ISR副本之后就可以返回了,如果leader掛了扔役,Kafka還可以從ISR中選舉出新的leader帆喇,如果這時候ISR為空,那么根據(jù)其他參數(shù)看是否選舉其他副本亿胸,這其實就是在高可用和消息不丟失之間的權(quán)衡了坯钦。另外retires重試次數(shù)設置大一些可以保證在生產(chǎn)過程消息不會丟失预皇。
- Kafka丟失消息:這里需要關注的主要就是Kafka的刪除策略,如果文件過大婉刀,或者是超過一段時間吟温,會被Kafka刪除。還有Kafka的持久化 方式路星,Kafka其實是充分利用了磁盤的頁緩存的溯街,那么如果寫入頁緩存,沒寫入磁盤的時候ack是否會返回洋丐?(這塊需要再查一下相關書籍)呈昔。
- 消費者丟失消息:這個其實也比較常見,如果設置Kafka自動提交偏移量友绝,那么可能消息偏移量提交之后堤尾,消費者掛了,消息還沒處理完迁客,那么這部分數(shù)據(jù)就丟失了郭宝。在消費者端解決的方式就是由消費端決定何時提交偏移量,設置enable.auto.commit為false
三掷漱、重復消費問題
這個方案有Kafka的內(nèi)置冪等性保證和事務粘室,但是對性能有損,雖好還是結(jié)合業(yè)務情況來保證冪等性卜范。
比如你拿個數(shù)據(jù)要寫庫衔统,你先根據(jù)主鍵查一下,如果這數(shù)據(jù)都有了海雪,你就別插入了锦爵,update 一下好吧。
比如你是寫 Redis奥裸,那沒問題了险掀,反正每次都是 set,天然冪等性湾宙。
比如你不是上面兩個場景樟氢,那做的稍微復雜一點,你需要讓生產(chǎn)者發(fā)送每條數(shù)據(jù)的時候侠鳄,里面加一個全局唯一的 id埠啃,類似訂單 id 之類的東西,然后你這里消費到了之后畦攘,先根據(jù)這個 id 去比如 Redis 里查一下,之前消費過嗎十电?如果沒有消費過知押,你就處理叹螟,然后這個 id 寫 Redis。如果消費過了台盯,那你就別處理了罢绽,保證別重復處理相同的消息即可。
比如基于數(shù)據(jù)庫的唯一鍵來保證重復數(shù)據(jù)不會重復插入多條静盅。因為有唯一鍵約束了良价,重復數(shù)據(jù)插入只會報錯,不會導致數(shù)據(jù)庫中出現(xiàn)臟數(shù)據(jù)蒿叠。
四明垢、消息積壓問題
消息積壓主要有以下原因:
消費者速度跟不上生產(chǎn)者的速度:這個時候,可以先看批次拉取的大小是否合理市咽,以及消費者的消費邏輯是否已經(jīng)使用多線程消費了痊银。如果還是跟不上消費速度,那么可以考慮同時增加partition和消費者大小施绎。
消費者掛了:先把消費者恢復溯革。
瞬時流量過大:如果是這個原因的話,如果積壓的不是特別多的話谷醉,等流量低的時候消費者自然會把積壓的數(shù)據(jù)消費完致稀。
五、高可用問題
Kafka架構(gòu)可以保證高可用
六俱尼、順序性問題
對于Kafka來說抖单,以topic為邏輯單位存儲,物理存儲結(jié)構(gòu)單位是partition号显,而topic切分成partition無法保證有序臭猜,但是partition是順序?qū)懙模梢员WC有序押蚤。如果我們需要按照某個維度保持有序的話蔑歌,可以設置消息的key