解決甩鍋的一大難題,就是留個憑證

原創:猿天地(微信公衆號ID:cxytiandi),歡迎分享,轉載請保留出處。

在多個團隊之間的一些業務關聯上,內部能夠Rpc的方式進行交互。某些業務其實不須要強關聯,這個時候就會用消息隊列進行解耦操做。好比下單後加積分,發短信通知的這類操做。sql

在用消息隊列的時候,咱們最須要關注的一個問題就是消息會不會丟失?數據庫

這裏的丟失指的就是要麼你程序有問題,沒有發送出去。要麼發送出去了,可是在某個節點上消息丟掉了,致使消費方沒有收到你發送的消息,從而引起業務問題。微信

對於消息丟失,有不少的解決方案。本文不聊怎麼在技術層面去防止消息丟失,聊另外一個話題:消息到底發沒發送?數據庫設計

在多團隊之間用消息解耦的場景下更容易出現這類問題,另外一個團隊的同窗找你,說大家的消息是否是沒發送啊,我這邊這條數據的狀態沒流轉,確定沒收到消息。微服務

而後你屁顛屁顛的去消息隊列的控制檯進行消息的查詢,發現確實查不到。主要問題在於這條數據是幾個月以前的了,發送記錄沒有保存這麼久,因此如今是有口難辯的這麼一個狀態。
spa

別人說你沒發,但你本身又拿不出來證據來證實本身發送過了消息。因此這個鍋你只能本身背了。這就是今天要聊的話題,凡事要留個憑證,方便往後好追溯,特別是關鍵的業務場景。設計

存儲發送記錄到數據庫

既然要留憑證,那麼就須要將憑證存儲起來。消息隊列的消息量大,確定不會所有永久存儲,通常都是存儲最近幾天的量,因此直接利用消息隊列去查有沒有發送只適合最近的消息,時間比較久的就無從追溯了。日誌

在消息發送後,能夠直接存儲到數據庫中,方便後面查詢發送記錄。其實就跟短信記錄同樣的,短信也常常會遇到說這個短信我沒收到,是否是沒發送啊之類的問題。隊列

存儲須要考慮的就是量的問題,若是大家天天的消息量很大,還須要存儲永久的數據,那麼就得拆分了,或者採用外置其餘數據庫進行單獨存儲,好比MongoDB之類的NoSql。消息隊列

存儲發送記錄到日誌

另外一種方案就是發送後直接輸出一條日誌便可,由於大部分公司都有統一的日誌平臺,去收集日誌進行存儲。這個方案就不用佔用DB的存儲或者說單獨弄一套Nosql存儲,比較省事。

可是須要注意的是日誌的存儲時間,像一些雲廠商的日誌服務是能夠設置存儲時間的,由於日誌的量越大,成本越高。

在好久以前就遇到過發消息實際上是打印了日誌的,可是存儲時間只有最近一個月。當別人來問你消息有沒有發送的時候,你會發現當時的日誌已經沒有了,因此咱們仍是須要進行永久存儲。

永久存儲也就意味着成本的提升,其實咱們能夠將日誌分類,普通的日誌能夠存儲時間短一點,一些有用的日誌能夠單獨進行輸出收集和永久存儲。這類日誌的量相對少一點,成本可控。

直接用本地消息表發送

除了用開源的消息隊列,不少公司也都會用本地消息表,單獨的消息服務,基於數據庫設計的消息隊列這些形式來發送消息。這些形式的特色就是自己就基於DB作的持久化,因此對於查找有沒有發送過消息是自然支持的。固然也有可能量大後即便分庫分表了,後期仍是要擴容或者按期歸檔,只要數據還在這個鍋就背不了。


關於做者:尹吉歡,簡單的技術愛好者,《Spring Cloud微服務-全棧技術與案例解析》, 《Spring Cloud微服務 入門 實戰與進階》做者, 公衆號猿天地發起人。