支付對賬系統序章:千萬級數據對賬怎麼這麼難?
支付對賬
很早 之前寫過一篇支付對賬相關文章,那時候負責對賬系統日均處理數量比較小。
那最近正在接手現在的對賬系統,由於當前系統日均數量都在千萬級,所以對賬系統架構與之前架構完全不一樣。
那就這個話題,聊聊如何實現千萬級數據支付的對賬系統。
什麼是對賬?
我們先來回顧下什麼是對賬?
也許你對對賬這個概念比較模糊,但是這個場景你肯定碰到過。
上班路上買了一個煎餅,加了根裡脊與王中王,然後你掃了老闆的二維碼付了 10 元錢。
你跟老闆說你已經付了 10 元錢,老闆看了下手機,果然有一條 10 元支付記錄,老闆確認收到錢,然後就把煎餅給你。
這個過程,你說你付了 10 元,老闆確認收到 10 元,這就是一隻簡單的對賬過程。
回到我們支付場景,用戶下單使用微信支付 100 元購買了一個狗頭抱枕,這時我們這邊會生成一條支付記錄,同時微信支付也會生成記錄。
那微信第二天就會生成一個賬單記錄,我們拿到之後把我們的交易記錄跟微信記錄逐筆核對,這就是支付對賬。
為什麼需要對賬?
正常支付的情況下,兩邊(我們/第三方支付渠道)都會產生交易數據,那支付對賬過程,兩邊數據一致,大家各自安好,不用處理什麼。
但是有些異常情況下,可能由於網路問題,導致兩邊數據存在不一致的情況,支付對賬就可以主動發現這些交易。
對賬可以說支付系統最後一道安全防線,通過對賬我們可及時的對之前支付進行糾錯,避免訂單差錯越積越多,最後財務盤點變成一筆糊塗賬。
支付對賬系統
開篇先來一張圖,先來看下整體對賬系統架構圖:
整個對賬系統分為兩個模組
- 對賬模組
- 差錯模組
對賬模組,主要負責對賬文件拉取,數據解析,數據核對,數據匯總等任務。
差錯模組是對賬模組後置任務,對賬模組核對過程產生無法核對成功的數據,這類數據件將會推送給差錯系統。
差錯系統將會根據規則生成差錯訂單,運營人員可以在後台處理這列數據。
今天這篇文章先不聊具體的系統設計,先來回顧下之前的對賬系統設計,簡單了解下對賬的整體流程。
對賬系統設計
對賬系統如果從流程上來講,其實非常簡單,引用一下之前文章流程圖:
//studyidea.cn/articles/2019/08/26/1566790305561.html
整體流程可以簡單分為三個模組:
- 本端數據處理
- 對端數據處理
- 本端數據與渠道端數據核對
本端數據指的是我們應用產生的支付記錄,這裡根據賬期(交易日期)與渠道編號獲取單一渠道的所有支付記錄。
對端數據指的是第三方支付渠道支付記錄,一般通過下載對賬文件獲取。
由於每個渠道下載方式,文件格式都不太一樣,對端數據處理的時候需要將其轉化統一數據格式,標準化在入庫存儲。
網上找了一份通用賬單,可以參考:
對端數據轉化存儲之後,對賬流程中,對端數據也需要跟本端數據一樣,獲取當前賬期下所有記錄。
兩端數據都獲取成功之後,接下來就是本地數據逐筆核對。
核對流程可以參考之前寫的流程:
上面流程其實也比較簡單,翻譯一下:
查找本端數據/對端數據,然後轉化存儲到 Map 中,其中 key 為訂單號,value 為本端/對端訂單對象。
然後遍曆本端數據 Map 對象,依次去對端數據 Map查找。如果能查找到,說明對端數據也有這筆。這筆核對成功,對端數據集中移除這筆。
如果查找不到,說明這筆數據為差異數據,它在本端存在,對端不存在 ,將其移動到差異數據集中。
最後,本端數據遍歷結束,如果對端數據集還存在數據,那就證明這些數據也是差異數據,他們在對端存在,本端不存在 ,將其也移動到差異數據集中。
PS:上述流程存在瑕疵,只能核對出兩邊訂單互有缺失的流程 ,但是實際情況下還會碰到兩邊訂單都存在,但是訂單金額卻不一樣的差異數據。這種情況有可能發現在系統 Bug,比如渠道端上送金額單位為元,但是實際上送金額單位為分,這就導致對賬兩端金額不一致。
之前對賬系統日均處理的支付數據峰值在幾十萬,所以上面的流程沒什麼問題,還可以抗住,正常處理。
但是目前的支付數據日均在千萬級,如果還是用這種方式對賬,當前系統可能會直接崩了。。。
千萬數據級帶來的挑戰
第一個,查詢效率。
本端/對端數據通過分頁查詢業務數據表獲取當天所有的數據。隨著每天支付數據累計,業務表中數據將會越來越多,這就會導致數據查詢變慢。
實際過程我們發現,單個渠道數據量很大的情況下,對賬完成需要一兩個小時。
雖然說對賬是一個離線流程,允許對賬完成時間可以久一點。但是對賬流程是後續其他任務的前置流程,整個對賬流程還是需要在中午之前完成,這樣運營同學就可以在下午處理。
第二個問題,OOM。
上面流程中,我們把把全部數據載入到記憶體中,小數據量下沒什麼問題。
但是在千萬級數據情況下,數據都載入到記憶體中,並且還是載入了兩份數據(本端、對端),這就很容易吃完整個應用記憶體,從而導致 Full GC,甚至還有可能導致應用 OOM。
而且這還會導致級聯反應,一個任務引發 Full GC,導致其他渠道對賬收到影響。
第三個問題,性能問題。
原先系統設計上,單一渠道對賬處理流程只能在單個機器上處理,無法並行處理。
這就導致系統設計伸縮性很差,伺服器資源也被大量的浪費。
千萬數據級對賬解決辦法
上面系統程式碼,實際上還是存在優化空間,可以利用單機多執行緒並行處理,但是大數據下其實帶來效果不是很好。
那主要原因是因為發生在系統架構上,當前系統使用底層使用 MySQL 處理的。
傳統的 MySQL 是 OLTP (on-line transaction processing),這個結構決定它適合用於高並發,小事務 業務數據處理。
但是對賬業務特性動輒就是百萬級,千萬級數據,數據量處理非常大。但是對賬數據處理大多是一次性,不會頻繁更新。
上面業務特性決定了,MySQL 這種 OLTP 系統不太適合大數據級對賬業務。
那專業的事應該交給專業的人去做,對賬業務也一樣,這種大數據級業務比較適合由 Hive、Spark SQL 等 OLAP去做。
總結
今天本篇文章只是一個序曲,主要聊聊對賬業務基本流程,聊聊之前系統架構在大數據下存在的問題。
後面文章再會介紹下大數據下對賬系統如何設計,對賬之後差錯數據如何處理,盡請期待。