分布式事務(wù)跨庫數(shù)據(jù)頻繁錯(cuò)亂?資金對賬差異難修復(fù),MySQL binlog+消息隊(duì)列最終一致性落地解法

在當(dāng)下微服務(wù)架構(gòu)普及的開發(fā)場景中,絕大多數(shù)業(yè)務(wù)系統(tǒng)都會(huì)按照業(yè)務(wù)模塊做數(shù)據(jù)庫拆分,將原本的單體單庫架構(gòu),拆分為用戶庫、交易庫、賬單庫、業(yè)務(wù)庫等多個(gè)獨(dú)立數(shù)據(jù)庫。拆分之后,系統(tǒng)的并發(fā)能力、擴(kuò)容能力和業(yè)務(wù)解耦效果都得到了大幅提升,但隨之而來的跨庫分布式事務(wù)數(shù)據(jù)不一致問題,成為了很多開發(fā)和運(yùn)維人員的核心困擾,尤其在涉及交易、記賬、資金統(tǒng)計(jì)的業(yè)務(wù)場景中,極易引發(fā)嚴(yán)重的對賬難題。

很多企業(yè)的業(yè)務(wù)系統(tǒng)都會(huì)出現(xiàn)這類共性問題:用戶扣款操作在交易庫執(zhí)行成功,但是賬單庫的入賬記錄沒有生成;或是上游業(yè)務(wù)數(shù)據(jù)更新完成,下游關(guān)聯(lián)庫的數(shù)據(jù)遲遲未同步;每日自動(dòng)對賬時(shí)總會(huì)出現(xiàn)金額差額、流水缺失、數(shù)據(jù)對不上的情況。這類問題不會(huì)直接導(dǎo)致系統(tǒng)崩潰,但會(huì)造成業(yè)務(wù)數(shù)據(jù)失真,需要運(yùn)維人員每天人工核對、手動(dòng)補(bǔ)數(shù)、修正差額,不僅耗費(fèi)大量人力成本,還容易出現(xiàn)人工操作失誤,給業(yè)務(wù)運(yùn)營帶來極大隱患。今天我們就從實(shí)際業(yè)務(wù)問題出發(fā),拆解跨庫數(shù)據(jù)不一致的核心原因、對賬痛點(diǎn),以及適配高并發(fā)業(yè)務(wù)的MySQL binlog+消息隊(duì)列最終一致性完整解決方案。

一、跨庫分布式事務(wù)數(shù)據(jù)不一致的核心問題根源

在單體單庫架構(gòu)中,我們依靠MySQL本地事務(wù)的ACID特性,就能輕松保證單次業(yè)務(wù)操作的原子性,要么全部執(zhí)行成功,要么全部回滾,數(shù)據(jù)一致性可以得到絕對保障。但多庫拆分之后,跨服務(wù)、跨庫的操作已經(jīng)脫離了本地事務(wù)的管控范圍,這也是數(shù)據(jù)錯(cuò)亂的根本原因。

分布式系統(tǒng)遵循CAP理論,無法同時(shí)滿足一致性、可用性和分區(qū)容錯(cuò)性,互聯(lián)網(wǎng)業(yè)務(wù)尤其是交易類業(yè)務(wù),普遍優(yōu)先保障高可用和分區(qū)容錯(cuò)性,只能放棄傳統(tǒng)的強(qiáng)一致性,這就注定跨庫操作必然會(huì)存在短暫的數(shù)據(jù)不一致窗口。具體落地過程中,數(shù)據(jù)不一致的觸發(fā)場景主要分為三類。

第一類是網(wǎng)絡(luò)異常導(dǎo)致的事務(wù)割裂??鐜鞓I(yè)務(wù)需要調(diào)用多個(gè)服務(wù)、操作多個(gè)數(shù)據(jù)庫,業(yè)務(wù)執(zhí)行過程中,一旦出現(xiàn)網(wǎng)絡(luò)超時(shí)、短暫斷連、網(wǎng)關(guān)抖動(dòng)等問題,就會(huì)出現(xiàn)部分庫執(zhí)行成功、部分庫執(zhí)行失敗的情況。比如用戶支付場景,交易庫成功扣除用戶余額,但是網(wǎng)絡(luò)波動(dòng)導(dǎo)致賬單庫寫入失敗,直接造成賬實(shí)不符。

第二類是服務(wù)宕機(jī)引發(fā)的未完成事務(wù)。業(yè)務(wù)執(zhí)行中途,應(yīng)用服務(wù)、數(shù)據(jù)庫服務(wù)重啟或宕機(jī),會(huì)導(dǎo)致分布式事務(wù)執(zhí)行中斷,已執(zhí)行的數(shù)據(jù)庫操作無法回滾,未執(zhí)行的操作無法繼續(xù)推進(jìn),形成永久的數(shù)據(jù)差異。

第三類是同步執(zhí)行的性能瓶頸引發(fā)的主動(dòng)降級。很多高并發(fā)業(yè)務(wù)為了保障接口響應(yīng)速度,會(huì)將部分非核心的對賬、記賬、統(tǒng)計(jì)操作改為異步執(zhí)行,若異步任務(wù)調(diào)度異常、執(zhí)行超時(shí),就會(huì)出現(xiàn)主庫數(shù)據(jù)更新完成,從庫、關(guān)聯(lián)庫數(shù)據(jù)滯后或缺失的問題,日積月累形成大量對賬差異數(shù)據(jù)。

二、跨庫操作引發(fā)的資金對賬核心痛點(diǎn)

相較于普通業(yè)務(wù)數(shù)據(jù)不一致,資金、交易類數(shù)據(jù)的錯(cuò)亂影響范圍更廣,痛點(diǎn)也更加突出,是企業(yè)數(shù)字化運(yùn)營中必須解決的核心問題,目前行業(yè)內(nèi)普遍面臨四大實(shí)操難題。

首先是對賬數(shù)據(jù)雙向不對稱,排查難度極大。分布式多庫架構(gòu)下,資金流水分散在多個(gè)數(shù)據(jù)庫中,每日對賬需要聚合多個(gè)庫的交易數(shù)據(jù)、賬單數(shù)據(jù)、余額數(shù)據(jù)。一旦出現(xiàn)金額差額,無法快速定位問題源頭,很難區(qū)分是扣款數(shù)據(jù)異常、入賬數(shù)據(jù)缺失還是同步延遲導(dǎo)致的臨時(shí)差異,單次問題排查往往需要耗費(fèi)數(shù)小時(shí)。

其次是人工修復(fù)成本高,容錯(cuò)率低。早期很多團(tuán)隊(duì)沒有自動(dòng)化的數(shù)據(jù)修復(fù)機(jī)制,出現(xiàn)對賬差異后,只能依靠運(yùn)維和開發(fā)人員手動(dòng)比對流水、補(bǔ)錄數(shù)據(jù)、修正金額。每日零散的異常數(shù)據(jù)會(huì)持續(xù)堆積,月末匯總對賬時(shí)差異數(shù)據(jù)量劇增,人工處理效率極低,且手動(dòng)操作極易出現(xiàn)二次錯(cuò)誤,加劇數(shù)據(jù)混亂問題。

再者是傳統(tǒng)分布式事務(wù)方案無法適配高并發(fā)對賬場景。行業(yè)內(nèi)早期常用的2PC、XA強(qiáng)一致性分布式事務(wù),雖然能實(shí)現(xiàn)數(shù)據(jù)強(qiáng)一致,但存在致命缺陷,事務(wù)鎖定時(shí)間長、接口響應(yīng)慢、吞吐量極低,完全無法適配高峰期的交易并發(fā)場景,一旦業(yè)務(wù)量上漲,就會(huì)出現(xiàn)接口超時(shí)、服務(wù)阻塞的問題,根本不適合資金高頻交易場景。而TCC補(bǔ)償事務(wù)雖然性能更高,但開發(fā)成本極高,每個(gè)業(yè)務(wù)場景都需要單獨(dú)編寫確認(rèn)、取消、補(bǔ)償邏輯,代碼侵入性極強(qiáng),維護(hù)難度極大。

最后是臨時(shí)數(shù)據(jù)不一致常態(tài)化,影響業(yè)務(wù)校驗(yàn)。很多業(yè)務(wù)接口會(huì)實(shí)時(shí)校驗(yàn)用戶余額、交易狀態(tài),跨庫同步的短暫延遲,會(huì)導(dǎo)致前端展示數(shù)據(jù)不準(zhǔn)、業(yè)務(wù)校驗(yàn)失敗,出現(xiàn)用戶明明扣款成功,卻提示余額不足,或是交易完成但賬單未顯示的問題,嚴(yán)重影響用戶使用體驗(yàn),同時(shí)也增加了對賬的干擾項(xiàng)。

三、MySQL binlog+消息隊(duì)列最終一致性方案核心原理

針對以上痛點(diǎn),目前互聯(lián)網(wǎng)行業(yè)高并發(fā)資金交易、對賬業(yè)務(wù)的主流落地方案,就是基于MySQL binlog結(jié)合消息隊(duì)列實(shí)現(xiàn)的最終一致性方案。該方案摒棄了傳統(tǒng)強(qiáng)一致性事務(wù)的性能短板,以“短暫不一致、最終全同步”為核心思路,兼顧系統(tǒng)高可用、高并發(fā)和數(shù)據(jù)一致性,同時(shí)代碼侵入性極低、維護(hù)成本小,完美適配跨庫資金對賬場景。

首先我們簡單說明核心組件的作用。MySQL binlog是MySQL的二進(jìn)制日志,數(shù)據(jù)庫中所有的增、刪、改操作都會(huì)被完整記錄在binlog日志中,日志包含操作語句、數(shù)據(jù)變更前后內(nèi)容、執(zhí)行時(shí)間、事務(wù)標(biāo)識等完整信息,是數(shù)據(jù)庫最真實(shí)、最可靠的數(shù)據(jù)變更憑證,且日志寫入與數(shù)據(jù)庫事務(wù)綁定,事務(wù)成功才會(huì)寫入binlog,事務(wù)回滾則不會(huì)生成日志,從根源上保證了日志數(shù)據(jù)的準(zhǔn)確性。

消息隊(duì)列則承擔(dān)異步解耦、可靠投遞、失敗重試的核心作用,負(fù)責(zé)中轉(zhuǎn)binlog解析后的變更事件,保障數(shù)據(jù)同步任務(wù)不丟失、不重復(fù)、可重試,解決網(wǎng)絡(luò)異常、服務(wù)宕機(jī)導(dǎo)致的同步失敗問題。

整個(gè)方案的核心邏輯非常清晰:不再由業(yè)務(wù)代碼主動(dòng)同步多庫數(shù)據(jù),避免業(yè)務(wù)代碼侵入和同步不穩(wěn)定問題,而是通過中間件實(shí)時(shí)監(jiān)聽MySQL的binlog日志,捕獲主庫的所有數(shù)據(jù)變更事件,將事件封裝為消息投遞到消息隊(duì)列,消費(fèi)者服務(wù)異步消費(fèi)消息,執(zhí)行跨庫數(shù)據(jù)同步、賬單寫入、資金記賬等操作,同時(shí)搭配重試、對賬、冪等機(jī)制,確保所有數(shù)據(jù)最終完全一致。

四、方案完整落地架構(gòu)與執(zhí)行流程

整套落地架構(gòu)分為業(yè)務(wù)層、數(shù)據(jù)庫層、日志監(jiān)聽層、消息隊(duì)列層、消費(fèi)執(zhí)行業(yè)務(wù)層、對賬兜底層六大模塊,各模塊職責(zé)清晰、完全解耦,具體執(zhí)行流程分為六個(gè)核心步驟,覆蓋完整的跨庫數(shù)據(jù)同步與對賬閉環(huán)。

第一步,業(yè)務(wù)正常執(zhí)行本地事務(wù)。用戶發(fā)起支付、轉(zhuǎn)賬、消費(fèi)等資金操作時(shí),業(yè)務(wù)服務(wù)僅操作本地核心數(shù)據(jù)庫,依靠MySQL本地事務(wù)保障當(dāng)前業(yè)務(wù)數(shù)據(jù)的原子性,快速完成業(yè)務(wù)響應(yīng),不會(huì)因?yàn)榭鐜焱竭壿嬜枞涌?,保障接口響?yīng)速度和系統(tǒng)并發(fā)能力。事務(wù)執(zhí)行成功后,MySQL自動(dòng)生成對應(yīng)的binlog變更日志。

第二步,binlog實(shí)時(shí)監(jiān)聽與日志解析。采用Canal、Maxwell等主流binlog監(jiān)聽中間件,實(shí)時(shí)監(jiān)聽數(shù)據(jù)庫binlog日志,精準(zhǔn)捕獲新增、修改、刪除等數(shù)據(jù)變更。中間件會(huì)模擬MySQL從庫的身份,訂閱主庫日志,不會(huì)對主庫業(yè)務(wù)造成任何性能壓力,同時(shí)精準(zhǔn)解析日志中的事務(wù)ID、變更字段、操作類型、業(yè)務(wù)流水號等核心信息,過濾無效日志,封裝為標(biāo)準(zhǔn)化的業(yè)務(wù)事件消息。

第三步,可靠消息投遞至消息隊(duì)列。解析完成的業(yè)務(wù)事件消息,會(huì)被批量、可靠投遞到消息隊(duì)列中。這里會(huì)開啟消息隊(duì)列的持久化機(jī)制,消息落地磁盤后再推送消費(fèi),避免服務(wù)重啟、宕機(jī)導(dǎo)致消息丟失。同時(shí)按照業(yè)務(wù)場景做消息分區(qū),交易、賬單、統(tǒng)計(jì)等消息分區(qū)隔離,避免不同業(yè)務(wù)消息相互干擾,保障消息有序消費(fèi)。

第四步,消費(fèi)者異步執(zhí)行跨庫業(yè)務(wù)操作。獨(dú)立的消費(fèi)服務(wù)監(jiān)聽消息隊(duì)列,有序消費(fèi)每條數(shù)據(jù)變更消息,根據(jù)消息內(nèi)容執(zhí)行跨庫數(shù)據(jù)同步、賬單生成、資金入賬、流水記錄等操作。整個(gè)過程為異步執(zhí)行,不影響主業(yè)務(wù)流程,徹底解決同步跨庫操作的性能瓶頸。

第五步,失敗消息自動(dòng)重試兜底。消費(fèi)過程中若出現(xiàn)數(shù)據(jù)庫連接失敗、網(wǎng)絡(luò)異常、數(shù)據(jù)鎖沖突等問題,導(dǎo)致消費(fèi)執(zhí)行失敗,消息不會(huì)直接丟棄,會(huì)被消息隊(duì)列捕獲,按照預(yù)設(shè)策略進(jìn)行重試。支持自定義重試次數(shù)和重試間隔,多次重試失敗的消息會(huì)進(jìn)入死信隊(duì)列,避免無效重試占用系統(tǒng)資源。

第六步,定時(shí)對賬校準(zhǔn)數(shù)據(jù)一致性。系統(tǒng)新增定時(shí)對賬任務(wù),每日固定時(shí)間遍歷所有交易流水、資金記錄,比對主庫與關(guān)聯(lián)庫的數(shù)據(jù)差異,針對死信隊(duì)列中未處理成功的異常消息,人工核查后手動(dòng)觸發(fā)補(bǔ)償執(zhí)行,同時(shí)自動(dòng)修復(fù)輕微數(shù)據(jù)差異,徹底杜絕永久數(shù)據(jù)不一致問題,保障每日資金對賬百分百準(zhǔn)確。

五、方案核心兜底機(jī)制,徹底解決對賬錯(cuò)亂問題

想要讓整套方案穩(wěn)定落地,徹底解決資金對賬難題,核心在于做好冪等性設(shè)計(jì)、消息可靠性保障、異常補(bǔ)償三大兜底機(jī)制,避免出現(xiàn)重復(fù)入賬、消息丟失、數(shù)據(jù)錯(cuò)亂等問題。

首先是全局冪等性設(shè)計(jì),杜絕重復(fù)對賬差異。binlog監(jiān)聽和消息消費(fèi)過程中,可能會(huì)出現(xiàn)日志重復(fù)推送、消息重復(fù)投遞的問題,若不做冪等控制,會(huì)導(dǎo)致同一筆交易多次入賬、多次統(tǒng)計(jì),直接引發(fā)資金對賬金額虛增。我們可以通過全局唯一的業(yè)務(wù)流水號、事務(wù)ID作為冪等鍵,消費(fèi)執(zhí)行業(yè)務(wù)操作前,先校驗(yàn)當(dāng)前流水號是否已處理完成,已處理則直接跳過,未處理則正常執(zhí)行,從根源上杜絕重復(fù)數(shù)據(jù)問題。

其次是消息全鏈路可靠性保障,杜絕數(shù)據(jù)丟失。整套鏈路實(shí)現(xiàn)“日志不丟、消息不丟、消費(fèi)不丟”三重保障。MySQL binlog日志持久化存儲,不會(huì)隨意丟失;消息隊(duì)列開啟消息持久化、ACK確認(rèn)機(jī)制,只有消費(fèi)者成功執(zhí)行完業(yè)務(wù)邏輯并返回ACK后,消息才會(huì)被刪除;未收到ACK的消息會(huì)持續(xù)重試,最大程度避免數(shù)據(jù)同步遺漏。

最后是異常數(shù)據(jù)自動(dòng)補(bǔ)償機(jī)制,降低人工成本。針對網(wǎng)絡(luò)波動(dòng)、服務(wù)宕機(jī)導(dǎo)致的同步失敗數(shù)據(jù),除了消息重試外,新增定時(shí)巡檢任務(wù),每小時(shí)掃描一次未同步、未入賬、狀態(tài)異常的交易數(shù)據(jù),自動(dòng)觸發(fā)補(bǔ)償同步。對于重試多次失敗的異常數(shù)據(jù),自動(dòng)匯總生成對賬差異報(bào)表,推送至運(yùn)維人員,無需人工逐一排查,大幅降低對賬和修復(fù)成本。

六、方案落地核心優(yōu)勢與業(yè)務(wù)適配性

相較于傳統(tǒng)的2PC、TCC、本地消息表等分布式事務(wù)方案,MySQL binlog+消息隊(duì)列的最終一致性方案,在資金對賬、跨庫數(shù)據(jù)同步場景中優(yōu)勢極為突出。第一,業(yè)務(wù)代碼零侵入,開發(fā)維護(hù)成本極低。整套同步邏輯完全依托中間件和異步任務(wù)實(shí)現(xiàn),不需要修改核心業(yè)務(wù)代碼,無需手動(dòng)編寫事務(wù)補(bǔ)償、回滾邏輯,新手開發(fā)也能快速落地。

第二,性能損耗極低,適配高并發(fā)場景。主業(yè)務(wù)流程僅執(zhí)行本地?cái)?shù)據(jù)庫事務(wù),無任何同步阻塞、事務(wù)鎖定操作,接口響應(yīng)速度快,系統(tǒng)吞吐量高,完全可以支撐大促、高峰期等高頻資金交易場景,不會(huì)出現(xiàn)服務(wù)卡頓、超時(shí)問題。

第三,數(shù)據(jù)一致性可控,徹底解決對賬難題。通過binlog精準(zhǔn)捕獲數(shù)據(jù)變更,搭配消息隊(duì)列可靠重試、定時(shí)對賬巡檢、冪等兜底機(jī)制,徹底杜絕永久數(shù)據(jù)不一致問題,日常對賬無差額、無遺漏,大幅減少人工運(yùn)維成本。

第四,架構(gòu)擴(kuò)展性強(qiáng)。后續(xù)新增業(yè)務(wù)數(shù)據(jù)庫、新增對賬場景時(shí),僅需調(diào)整binlog監(jiān)聽規(guī)則和消息消費(fèi)邏輯,無需重構(gòu)整體架構(gòu),能夠快速適配業(yè)務(wù)迭代升級,適配絕大多數(shù)中小規(guī)模到大規(guī)模的分布式業(yè)務(wù)系統(tǒng)。

在實(shí)際業(yè)務(wù)落地中,該方案已經(jīng)廣泛應(yīng)用于支付記賬、訂單結(jié)算、積分變動(dòng)、流水統(tǒng)計(jì)等各類需要跨庫數(shù)據(jù)同步、精準(zhǔn)對賬的場景,完美解決了傳統(tǒng)分布式事務(wù)方案性能差、成本高、數(shù)據(jù)錯(cuò)亂的痛點(diǎn),是目前性價(jià)比最高、穩(wěn)定性最好的最終一致性落地方案。

https://hpqsh.tiancebbs.cn/xzyx/535354.html

http://blog.nxtcbmw.cn/forum-shangwu-1.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容