在公衆號回覆課程,免費獲取JAVA全棧課程
做者 | 顏 羣java
公衆號 | 大數據和人工智能技術git
前兩篇請戳:
web
本文解決最後兩個問題:在使用MQ發送消息的過程當中,數據庫
1.如何避免消息被重複消費編程
2.如何處理消息積壓問題
服務器
如何避免消息被重複消費
在使用MQ的過程當中,各類異常狀況均可能形成消息被重複消費。微信
例如不少類型的MQ都使用了offset(偏移量)記錄每一個消息的序號,用於保證消息的順序傳輸或者在出現災難時可以從指定序號的消息恢復傳輸。網絡
但試想如下場景:假設消息的處理邏輯是「先消費消息,再更新offset」,那麼當消息剛剛被消費完畢但尚未來得及更新offset時就出現故障宕機,MQ就會在恢復啓動時再次消費剛剛已經被消費過的消息,即出現了重複消費的狀況。所以,不管是採用了哪一種協議的MQ,都須要思考如何避免消息被重複消費的問題。
實際上不只僅是MQ,在分佈式系統的各個服務之間在相互調用時也須要解決「重複消費」的問題。例如在分佈式秒殺系統中,若是「訂單服務」成功調用了「支付服務」(即已經支付成功),但「支付服務」在做出響應時因爲網絡等緣由未能成功的響應「訂單服務」,就會形成「訂單服務」沒法更新支付狀態,最終就可能致使用戶誤覺得支付無效而從新再發起一次新的支付請求,從而致使用戶重複消費的狀況,如圖所示。
可見這種「重複消費」問題廣泛存在於各個分佈式項目當中,所以必須妥善解決。好消息是,解決的思路也是通用的——能夠藉助「冪等性原則」解決。
冪等性原則是對調用服務次數的一種限制,即不管對某個服務提供的接口調用屢次或是一次,其結果都是相同的。
若是從功能的角度看來,任何一個操做都是CRUD中的一種。但對於「重複消費」這個問題而言,咱們只須要研究「增長」和「修改」兩種操做,即「查詢」和「刪除」是不須要考慮冪等性的,由於「重複查」和「重複刪」對邏輯而言是沒有任何影響的。
「冪等性」是一個原則,它的具體實現方式也是五花八門。咱們本次主要介紹如何實現「增長」操做的冪等性,其核心思路主要有兩種:使用數據庫主鍵或去重表,以下所示。
根據數據庫主鍵實現冪等性
核心就是利用主鍵(或惟一約束)的「惟一性」來保證插入數據的惟一。例如,在用戶下單時,能夠在「訂單服務」中生成一個「訂單id」,而後用此「訂單id」的值再做爲「支付服務」的「支付id」值。若是出現了重複支付,就會違反主鍵的惟一約束,從而避免重複消費的場景。固然,本段介紹的「直接用訂單id做爲支付id」只是爲了說明這種使用主鍵實現冪等性的原理,在實際開發時,咱們也能夠對這兩個id進行一些映射處理,或者使用聯合主鍵也是一種很好的實現策略。
根據去重表實現冪等性
可使用集合或者Redis構建一張「去重表」,表中存放的是全局惟一的id值。當用戶每次發起請求時,先查看「去重表」中是否已有這次支付操做的id值,若是已有則直接返回「成功」;若是沒有,就說明尚未進行實際的支付操做,此時就進行支付操做,並在支付成功後將id值寫入「去重表」中,防止重複消費。
以上兩種思路可以實現大部分「增長」操做的冪等性。對於「修改」操做,你們能夠參考版本控制軟件(如svn、git)中防止提交衝突的CAS算法。例如在svn中,當A用戶修改並提交了數據後,B用戶是沒法直接提交的,不然就會出現衝突。這種版本控制的思路,就能夠拿來實現「修改」操做的冪等性,即當第一次修改數據後,以後若是再次修改,就應該給予錯誤提示。
如何處理消息積壓
消息隊列自己是一種緩衝區,而緩衝區就會受自身容量的限制。例如在秒殺系統中,當用戶請求的速度(生產者)大於服務器處理的速度(消費者)時,用戶請求(消息)就會積壓在隊列中,而且隨着時間的延長,積壓的請求也會愈來愈多,若是不予處理就會溢出隊列。
處理消息積壓最直接的方式就是水平擴容,即增長Consumer和分區的數量,用集羣的思路來處理。
或者,也能夠將積壓的消息以異步的方式寫到其餘多個新隊列中,以後再由各個新隊列分別處理。但要注意,爲了防止宕機形成的消息丟失,必定要按期將消息進行持久化或者記錄日誌。
此外,還要區分當前系統的實時性,若是對實時性要求較低就把重點放在MQ的擴容上,若是實時性較高就須要提升併發性能。最後,當發生消息積壓時,必定要認真審查已有代碼和異常日誌,檢查一下MQ的併發值、吞吐量等重要參數,再看看是否存在反覆批量重試的消息。
- 完 -
推薦閱讀
▲
在「大數據和人工智能技術」聊天對話框回覆如下關鍵詞,可得到相關信息喲
回覆【資料】獲取JAVA全棧視頻的配套資料
回覆【最新課程】獲取一門還沒有公開的高級課程(不按期更換)
回覆【提問】獲取免費答疑方式
回覆【課程】獲取JAVA全棧視頻教程 + 配套資料
回覆【軟件】獲取經常使用的開發軟件(逐步完善)
回覆【億級源碼】獲取本號做者出版的《億級流量Java高併發與網絡編程實戰》一書配套源碼
回覆【javase】獲取JAVA視頻教程
回覆【數據庫】獲取數據庫視頻教程
更多課程,逐步開放...
本文分享自微信公衆號 - 大數據和人工智能技術(Big_Data-AI)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。