寫數據庫mq消息事務一致性解決方案

原文連接:https://cloud.tencent.com/developer/article/1478827數據庫

若是咱們要在服務化拆分中使用消息隊列,那麼咱們須要解決哪些問題呢?首先去哪兒網提供了旅遊產品在線預訂服務,那麼就涉及電商交易,在電商交易中咱們認爲數據的一致性是很是關鍵的要素。那麼咱們的 MQ 必須提供一致性保證。網絡

MQ 提供一致性保證又分爲兩個方面。發消息時咱們如何確保業務操做和發消息是一致的,也就是不能出現業務操做成功消息未發出或者消息發出了可是業務並無成功的狀況。舉例來講,支付服務使用消息通知出票服務,那麼不能出現支付成功,可是消息沒有發出,這會引發用戶投訴;可是也不能出現支付未成功,可是消息發出最後出票了,這會致使公司損失。總結一下就是發消息和業務須要有事務保證。一致性的另外一端是消費者,好比消費者臨時出錯或網絡故障,咱們如何確保消息最終被處理了。那麼咱們經過消費 ACK 和重試來達到最終一致性。運維

3、利用數據庫事務解決一致性問題server

提到一致性,你們確定就想到事務,而一提到事務,確定就想到關係型數據庫,那麼咱們是否是能夠藉助關係型 DB 裏久經考驗的事務來實現這個一致性呢。咱們以 MySQL 爲例,對於 MySQL 中同一個實例裏面的 db,若是共享相同的 Connection 的話是能夠在同一個事務裏的。如下圖爲例,咱們有一個 MySQL 實例監聽在 3306 端口上,而後該實例上有 A,B 兩個 DB,那麼下面的僞代碼是能夠跑在同一個事務裏的隊列

有了這層保證,咱們就能夠透明的實現業務操做和消息發送在同一個事務裏了,首先咱們在公司全部 MySQL 實例裏初始化出一個 message db,這個能夠放到自動化流程中(聽說在去哪兒由運維團隊完成),對應用透明。而後咱們只要將發消息與業務操做放到同一個 DB 事務裏便可。事務

咱們來看一個實際的場景,在支付場景中,支付成功後咱們須要插入一條支付流水,而且發送一條支付完成的消息通知其餘系統。那麼這裏插入支付流水和發送消息就須要是一致的,任何一步沒有成功最後都會致使問題。那麼就有下面的代碼get

上面的代碼能夠用下面的僞代碼解釋消息隊列

實際上在 producer.sendMessage 執行的時候,消息並無經過網絡發送出去,而僅僅是往業務 DB 同一個實例上的消息庫插入一條記錄,而後註冊事務的回調,在這個事務真正提交後消息才從網絡發送出去,這個時候若是發送到 server 成功的話消息會被當即刪除掉。而若是消息發送失敗則消息就留在消息庫裏,這個時候咱們會有一個補償任務會將這些消息從消息庫裏撈出而後從新發送,直到發送成功。整個流程就以下圖所示產品

一、begin tx 開啓本地事務自動化

二、do work 執行業務操做

三、insert message 向同實例消息庫插入消息

四、end tx 事務提交

五、send message 網絡向 server 發送消息

六、reponse server 迴應消息

七、delete message 若是 server 回覆成功則刪除消息

八、scan messages 補償任務掃描未發送消息

九、send message 補償任務補償消息

十、delete messages 補償任務刪除補償成功的消息

相關文章
相關標籤/搜索