微服務信息同步方案(數據依賴一致性問題)
_ 作者:牛牛碼特_
juejin.cn/post/6844903924915240974
背景
微服務場景下需要同步信息的場景。
還是前文的栗子: 如下微服務
-
支付服務:負責完成支付操作,其中有支付流水數據。
-
賬單服務:指定時間生成賬單給用戶,其中有賬單流水數據。
此時產品上有個需求,在支付管理端根據是否出賬搜索支付流水,而出賬是賬單服務的功能。所以這裏涉及到信息的同步,那麼,我們怎麼保證同步一定能成功呢(最終一致性)。
消費者
保證在隊列中的消息,一定會被消費。用白話來講,就是不停消費直到成功。
方式比較簡單:消息隊列都使用手動提交。處理完了,再保證提交。儘量遵循觸發 - 查詢機制,提供可重入性,即消息隊列只傳遞 id 這種非實質信息,收到之後再通過 rpc 查詢拉取完整數據來更新。
生產者
主要是發送消息到隊列這步的可靠性考量
方案一:淺嘗輒止
以遞增的時間間隔重試 5 次。如果失敗了,上報到日誌和告警,人工介入。同時,具體業務準備好重試的腳本。根據實時的情況進行處理。優點:
- 簡單,能解決瞬間的網絡抖動造成的失敗。
缺點:
- 可靠性低。在消息隊列故障 30 分鐘這種場景下,無法自動恢復,同時從日誌撈取信息,也不是特別方便。
方案二:內有波瀾
失敗之後,內存維護一個重試隊列,先由 5,10,20, 40, 80, 160, 320s 的間隔重試。之後以 5 分鐘一次的間隔請求。同時,也要打入日誌系統,告警通知。
優點:可靠性會比一高很多,在消息隊列故障 30 分鐘這種場景下,也能自動恢復。可以做成 package 的方式,方便接入。
缺點:
- 服務重啓或者機器掛了,消息就丟了。
限制:
- 消息處理需要遵循觸發 - 查詢機制
方案三:內有波瀾 plus
失敗之後,內存維護一個重試隊列,先由 5,10,20, 40, 80,160, 320s 的間隔重試。然後 append 到本地文件,同時以 5 分鐘一次的頻率做重試。重試完成之後,從磁盤中刪除對應信息。當服務重啓,從磁盤把數據導入內存即可。
優點:
-
可靠性會比一高很多,在消息隊列故障 30 分鐘這種場景下,也能自動恢復,可以做成包的方式。
-
具有比較強的通用型
缺點:
- 增加了和磁盤打交道的邏輯,引入了文件 io。
限制:
- 消息處理需要遵循觸發 - 查詢機制
方案四:有備無患
實現任務重試微服務,該服務通過維護一張任務表,重試任務直到成功。相當於是消息隊列這個可靠中間件有問題,就丟給這個重試服務這個自己實現的 “中間件”。
優點:
-
可靠性會比一高很多,在消息隊列故障 30 分鐘這種場景下,也能自動恢復。
-
具有比較強的通用性。
缺點:
- 成本變高,需要額外服務。同時,如果服務也掛了,還是得依賴上報。(當然,上報也可能掛了)
限制:
- 消息處理需要遵循觸發 - 查詢機制
以上方案中,三,四基本能解決重試階段寫入消息隊列的可靠性問題。但針對另一個場景:正想寫本身服務就沒了的情況(比如 oom 導致服務被系統 kill 了) 還是不行。
方案五:先入爲主
要做變更之前,先寫入到消息同步微服務,告訴他要做什麼事(把什麼消息放入消息隊列),和流程最長執行時間,以及發給誰。該服務維護一張任務表,任務初始處於未激活狀態。
等業務做完要同步的時候,再 rpc 請求觸發激活。
任務管理微服務如果發現一個任務,超過最長執行時間沒有激活。就說明激活 rpc 失敗了,或者是服務崩潰,本身就沒做變更。此時,自動激活即可。
優點:完全可靠(事務可能還是會失敗,可靠指數據一定最終一致)。
缺點:
-
開發成本比較大,同時會增加消息調用。
-
增加一個節點,事務失敗得可能性更高。
限制:
- 消息處理需要遵循觸發 - 查詢機制
總結
推薦:方案三
推薦理由:成本不高,可靠性較強。可靠度 99.99%。(此處不論代碼本身 bug)
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/RMMOB8cLkNxz5_HTsMEOLA