解決甩鍋的一大難題,就是留個憑證
本文轉(zhuǎn)載自微信公眾號「猿天地」,作者尹吉歡。轉(zhuǎn)載本文請聯(lián)系猿天地公眾號。
在多個團隊之間的一些業(yè)務關聯(lián)上,內(nèi)部可以 Rpc 的方式進行交互。某些業(yè)務其實不需要強關聯(lián),這個時候就會用消息隊列進行解耦操作。比如下單后加積分,發(fā)短信通知的這類操作。
在用消息隊列的時候,我們最需要關注的一個問題就是消息會不會丟失?
這里的丟失指的就是要么你程序有問題,沒有發(fā)送出去。要么發(fā)送出去了,但是在某個節(jié)點上消息丟掉了,導致消費方?jīng)]有收到你發(fā)送的消息,從而引發(fā)業(yè)務問題。
對于消息丟失,有很多的解決方案。本文不聊怎么在技術層面去防止消息丟失,聊另一個話題:消息到底發(fā)沒發(fā)送?
在多團隊之間用消息解耦的場景下更容易出現(xiàn)這類問題,另一個團隊的同學找你,說你們的消息是不是沒發(fā)送啊,我這邊這條數(shù)據(jù)的狀態(tài)沒流轉(zhuǎn),肯定沒收到消息。
然后你屁顛屁顛的去消息隊列的控制臺進行消息的查詢,發(fā)現(xiàn)確實查不到。主要問題在于這條數(shù)據(jù)是幾個月之前的了,發(fā)送記錄沒有保存這么久,所以現(xiàn)在是有口難辯的這么一個狀態(tài)。
別人說你沒發(fā),但你自己又拿不出來證據(jù)來證明自己發(fā)送過了消息。所以這個鍋你只能自己背了。這就是今天要聊的話題,凡事要留個憑證,方便日后好追溯,特別是關鍵的業(yè)務場景。
存儲發(fā)送記錄到數(shù)據(jù)庫
既然要留憑證,那么就需要將憑證存儲起來。消息隊列的消息量大,肯定不會全部永久存儲,一般都是存儲最近幾天的量,所以直接利用消息隊列去查有沒有發(fā)送只適合最近的消息,時間比較久的就無從追溯了。
在消息發(fā)送后,可以直接存儲到數(shù)據(jù)庫中,方便后面查詢發(fā)送記錄。其實就跟短信記錄一樣的,短信也經(jīng)常會遇到說這個短信我沒收到,是不是沒發(fā)送啊之類的問題。
存儲需要考慮的就是量的問題,如果你們每天的消息量很大,還需要存儲永久的數(shù)據(jù),那么就得拆分了,或者采用外置其他數(shù)據(jù)庫進行單獨存儲,比如 MongoDB 之類的 NoSql。
存儲發(fā)送記錄到日志
另一種方案就是發(fā)送后直接輸出一條日志即可,因為大部分公司都有統(tǒng)一的日志平臺,去收集日志進行存儲。這個方案就不用占用 DB 的存儲或者說單獨弄一套 Nosql 存儲,比較省事。
但是需要注意的是日志的存儲時間,像一些云廠商的日志服務是可以設置存儲時間的,因為日志的量越大,成本越高。
在很久之前就遇到過發(fā)消息其實是打印了日志的,但是存儲時間只有最近一個月。當別人來問你消息有沒有發(fā)送的時候,你會發(fā)現(xiàn)當時的日志已經(jīng)沒有了,所以我們還是需要進行永久存儲。
永久存儲也就意味著成本的提高,其實我們可以將日志分類,普通的日志可以存儲時間短一點,一些有用的日志可以單獨進行輸出收集和永久存儲。這類日志的量相對少一點,成本可控。
直接用本地消息表發(fā)送
除了用開源的消息隊列,很多公司也都會用本地消息表,單獨的消息服務,基于數(shù)據(jù)庫設計的消息隊列這些形式來發(fā)送消息。這些形式的特點就是本身就基于 DB 做的持久化,所以對于查找有沒有發(fā)送過消息是天然支持的。當然也有可能量大后即使分庫分表了,后期還是要擴容或者定期歸檔,只要數(shù)據(jù)還在這個鍋就背不了。
關于作者:尹吉歡,簡單的技術愛好者,《Spring Cloud 微服務-全棧技術與案例解析》, 《Spring Cloud 微服務 入門 實戰(zhàn)與進階》作者, 公眾號猿天地發(fā)起人。