本篇文章主要聊聊如何設計千萬級別的對賬系統。其他一些業務問題可以參看對賬清分設計總概覽。
目前系統運行的對賬總情況:對賬日交易量兩千萬,交易金額50億,對賬時間5分鐘以內
本篇文章分兩個模塊 第一個模塊主要文字描述下目前系統對賬的流程,第二個模塊主要講述系統對賬的發展歷程
第一個模塊:
- 對賬主要幹些什麼
支付系統對賬主要幹些什麼事情呢,其實同樣的對賬系統差不多,每家公司業務不一樣,可能引申出來的含義不一樣但總體對賬流程大同小異。
支付對賬系統的設計時,一般將對賬系統分爲五個模塊,每個模塊負責自己的職能。
文件下載模塊:下載第三方通道的對賬單文件,目前主要是微信支付寶銀聯對賬單文件
文件解析模塊:創建不同的解析器,根據第三方對賬文件解析適配成平臺可以處理的對賬記錄
對賬處理模塊:對賬的業務邏輯處理,根據解析到的第三方對賬單與支付訂單逐筆比對,這個是核心 第二個模塊會詳細介紹
差錯處理模塊:處理上述比對過程的差錯數據,針對不同的類型訂單進行衝正通知補單等
數據彙總模塊: 根據業務將對賬數據彙總,比如按商戶支付類型彙總做報表查詢,同時默認生成一些大商戶渠道等對賬單文件以方便快速下載
整個功能圖:
1、文件下載
目前系統每天定時設置通道任務(任務建立優先大通道 同時任務時間儘量錯開),
設置通道任務的目的有兩個 一個防止重複對賬單下載 另一個需要在對賬結束的時候將對賬的結果信息保存 防止重複對賬,所以這裏通道任務狀態的修改可以使用數據庫樂觀鎖實現。根據不同的通道(通道主要保存了第三方的信息比如下載方式如ftp/sftp/http),技術實現上使用apache開源工具即可,重試次數和間隔的設置需要小心,重試太頻繁,容易把服務器打死.;時間間隔太大,又會阻塞後續處理步驟。5~10分鐘是一個合適的重試間隔區間。下載的時候可以使用多線程技術(java可以使用fork/join模型)
文件下載流程:
定時任務在凌晨創建下載任務(優先大通道,時間錯開),一般都是生成前一日的對賬任務,根據任務下載第三方對賬單,下載對賬單之前判斷本地sftp是否已有第三方對賬單,如果有直接從sftp下載讀取,如果沒有,則根據任務批量多線程方式下載第三方對賬單,保存到本地sftp,驗籤成功後,解析對賬單...
2、文件解析
文件解析主要是將下載的第三方對賬文件解析成我們可以對賬的數據類型並且入庫。一般對賬文件都是壓縮且加密的,所以需要根據不同的對賬單做不同的解析,因此也可以設計成不同的解析模板,使用工廠模式將不同格式的文件解析成可以對賬的統一數據類型。
對賬文件中包含的主要信息有:商戶訂單號、交易流水號、交易時間、支付時間、付款方、交易金額、交易類型、交易狀態這些字段。
4、對賬處理
對賬處理也是對賬的核心邏輯,具體分爲以下的幾個步驟來實現:
A.查詢平臺交易的訂單
B.查詢第三方支付對賬單
C.以銀行訂單爲基準對賬邏輯:以銀行的交易數據爲基準,遍歷所有平臺的交易(包括未成功的訂單),找出訂單號相同但支付狀態不一致的訂單,在進行對比金額存入差錯池。如果沒有在平臺的交易中找到此訂單,再從緩存池中遍歷查找,找到對應的平臺訂單驗證金額是否一致,不一致進入差錯池。如果在緩存池匯中依然沒有找到對應的訂單,直接進入差錯池,記錄平臺漏單。同時統計對賬相關金額和訂單數。
注意系統設計時 需要考慮對賬的可擴展性,比如使用以第三方平臺訂單爲準對賬 或者只用本地對賬單對賬(在第三方對賬單沒到賬之前 臨時對賬特別有用) 具體來說可以通過通道任務來設置
需要對賬:比金額====一致 獲取對平的訂單的對賬結果 --》 分發隊列 Queue分發
比金額====不一致 進入異常訂單
平臺有第三方沒有 進入異常訂單 平臺掛賬
本地對賬:獲取對平的訂單的對賬結果 --》 分發隊列 Queue分發
第三方有,本地沒有:代表平臺改天沒有數據或平臺庫裏都沒這筆訂單:
成功訂單,調用第三方接口去同步訂單的狀態,時間 金額 並寫入數據庫繼續比對
記錄平臺少訂單的異常記錄
5、對賬統計
根據對賬處理中,統計的相關信息包括:對賬完成時間、對賬是否成功、平賬的金額和訂單數、差錯的金額和訂單數、商戶日結數據,商戶品牌費等其他信息。
對賬統計完成後還需生成本系統對賬單文件供平臺使用者下載
如何生成平臺對賬單:根據優先常用的方式。具體方式爲通過數據分析針對大商戶大渠道取優先下載,商戶經常下載的取優先下載, 可以使用redis隊列zsort排序,定時器撈出redis隊列,提前生成好對賬單,如果商戶在平臺下載對賬單時此時沒有對賬單可以通過異步方式後臺下載,下載好後保存到sftp,下載後返回給前端,同時redis隊列針對該商戶打一分,再第二天對賬時根據改隊列重新優先級提前生成好當日的對賬單文件,這樣使用該方式可以有效的減少平臺對賬單生成過程中對系統的影響
6、差錯處理
在一般系統中,差錯處理分爲兩種,一種人工來處理,一種系統自動來處理。
主要有如下情況:
本地未支付,第三方已支付。這主要是本地未正確接收到第三方下發的異步通知導致。 一般處理是將本地狀態修改爲已支付,mq通知業務方即可。
本地已支付,第三方支付已支付,但是金額不同,這個需要人工覈查。
本地已支付,但是第三方支付中無記錄;或者本地無記錄,第三方支付有記錄。前者需要掛賬處理 後者是銷賬處理,具體原因需具體分析
支付訂單掛帳:第三方賬單今天沒有推送這筆訂單(這筆訂單也不會結算錢給我們),我們就要把這個訂單掛帳,並且是不結算(第三方沒個我們錢,我們也不能結算給商戶)
支付訂單銷賬:第三方賬單第N天推送了這筆訂單(這筆訂單今天的錢給我們了),我們就要把這個訂單銷賬,並且要結算(第三方給了我們錢,我們就要結算給商戶、渠道)
- 對賬優化里程
第二個模塊 講述本系統從無到有 ,以及一些變更 優化的點
|
當時情況 |
優缺點 |
目標 |
V1.0初期 |
當時考慮就是快速上線 基本考慮的是純內存+多線程方式 |
優點是快速上線滿足目前業務 缺點是針對交易量大時 內存佔用過多 |
快速上線 支持訂單百萬級 交易金額十億內 對賬時間半個鐘頭 |
V2.0 中期 線上 |
採用通道+商戶hash+redis緩存+jdbc分時訂單獲取方式 |
優點通過通道和商戶hash將數據隔離 可以快速擴機多臺 缺點是對賬時 第三方對賬單解析後純內存 內存還是佔用過高 |
支持訂單千萬級 交易金額五十億內 對賬時間五分鐘 |
V3.0 規劃 |
解決v2.0問題 同時優化數據庫查詢 |
減少內存消耗 |
訂單通知改用mysql,訂單表和訂單明細表合二爲一 去掉不必要索引 |