美团配送资金安全治理之对账体系建设
https://tech.meituan.com/balanceAccounts.html
前言
隨著美團配送業務的飛速發展,單量已經達到千萬級別,同時每天產生的資金額已經超過幾千萬,清結算系統在保證線上服務穩定可靠的前提下,如何系統化的保障資金安全是非常核心且重要的課題,配送清結算系統經過近3年的建設和打磨,在資金安全保障的多個方面均有一些總結和實踐,保障資金安全是值得系統思考的課題,只言片語難以全面概括,需要更多的著墨才能較完整闡述,本文側重點會闡述“對賬”的概念,在支付&清結算領域,這是一個非常重要的專業名詞,下文將介紹“對賬”在分布式系統建設中的實踐和解決方案,力求在系統覆蓋度、資金準確性、時效等多個維度為系統資金安全保駕護航,實現更健壯可靠的資金履約。
背景&問題
隨著美團外賣配送事業的蓬勃發展,配送清結算業務的復雜性也在不斷的增高,總結起來,主要有以下幾個特點:
- 場景多:包括專送、眾包、快送、跑腿、外部單等多條業務線;訂單補貼、活動發放、獎懲、餐損、打賞、保險等多種結算場景;對接外部十多個系統。
- 鏈路長:清結算內部經歷定價、記賬、匯總賬單、付款等多個流程。
- 單量大:目前日單量已達到千萬級別。
在這樣的業務背景下,我們的系統可謂險象環生。因業務高度復雜,稍有不慎就會出現問題,面對千萬級的日單量,同時還要確保結算金額的準確,這就讓我們對問題的容忍度變得極低。這也給我們的資金安全保障造成了巨大的挑戰。下面我們列舉了一些系統日常運行過程中出現的問題。
場景:
可以看出,這些都是一些上下游交互的邊界場景,以及遇到的問題。當然不僅限于這些場景,凡是有系統交互、數據交互邊界的場景,都會出現此類問題,我們稱之為“一致性問題”。經粗略統計,我們清結算系統建立以來有70%左右的問題都屬于一致性問題。
導致一致性問題的原因有很多,諸如:
- 冪等、并發控制不當。
- 基礎環境故障:比如網絡、數據庫、消息中間將發生故障。
- 其他代碼bug。
目前配送的日結算金額已達到千萬級別,每個一致性問題都有可能給我們整個美團點評造成巨大的損失。因此如何解決系統的一致性問題成為我們保障資金安全的重中之重。關于一致性問題,業內已經論述的非常成熟了,搜索引擎中搜索“一致性問題”,隨處可見此概念的定義、問題闡述、意義以及解決思路,諸如:
- 強一致性協議: 兩階段提交、三階段提交、TCC (Try-Confirm-Cancel)等
- 最終一致性: 主動輪詢、異步確保、可靠消息、消息事務等
這些手段的目標都是在事中避免問題的發生。但是在實際場景中,無論是系統的內部邏輯還是外部環境都十分復雜多變、不可預知,我們很難完全避免問題。因此事后對于問題數據的發現以及修復就顯得尤為重要。這些也正是我們這篇文章要論述的“對賬”的核心使命。我們力求總結對賬領域內最專業的思路和方法,并結合自身的業務特點,建設配送清結算的對賬體系,構筑配送資金安全的堅固防線。在系統的整個構建過程中我們主要圍繞以下幾個目標:
- 場景覆蓋的完整性:無死角覆蓋清結算業務涉及的各個場景。
- 問題發現的準確性:能夠準確的發現問題,保證不漏報,不誤報。
- 問題處理的實時性:盡可能縮短問題處理的周期,極力避免可能造成的損失。
下面開始正式介紹美團配送清結算對賬體系的構建經驗。
對賬的定義
對賬的概念隨著金融、互聯網行業的發展,定義上也經歷了幾個階段的變化,如下:
- stage 1 :對賬最初來源于會計核算,是為保證賬簿記錄正確可靠,對賬簿中的相關數據進行檢查和核對的工作。
- stage 2 :隨著互聯網金融或電商行業的發展,對賬也擴大了應用范圍,這一時期,對賬是指在固定周期內,支付使用方和支付提供方(銀行和第三方支付)相互確認交易、資金的正確性,保證雙方的交易、資金一致正確。
- stage 3 :從廣義來看,所有的跨端系統之間的數據核對都應該叫對賬,主要是檢查和發現數據在流轉過程中的不一致問題。通常分為信息流的核對和資金流的核對。信息流核對主要是對業務數據之間的核對,資金流是對資金交易數據進行核對。
對賬系統的構建思路
系統概況
配送結算做為核心交易履約系統,上游對接了訂單、獎懲、活動等十多個外部系統,下游又承擔了對接支付平臺、財務系統的職責,不僅“承上啟下”,而且涉及業務復雜。而系統內部又歷經定價、計費(清算)、記賬、匯總賬單、付款等多個環節,系統的高度復雜性給對賬的全面性和準確性造成了極大的困難,如圖:
為了系統更加專業化的實現對賬、做好對賬,我們對支付、清結算等資金領域進行了體系化的調研和學習,并結合業務的自身的特點,總結了一套對賬系統構建的思路方法,并基于該思路進行了較完整的系統化實現。
設計思路
從整體來看,按照時序維度的先后,系統對賬主要分為三階段的工作。分別是數據準備、數據核對和差錯處理。在對賬專業概念中,數據核對和差錯處理又叫軋賬和平賬。三個環節緊密相連,從前期準備、問題發現、問題處理三個角度展開對賬工作。
數據準備
數據準備,顧名思義,我們需要把對賬所需的全部數據,接入到我們的對賬系統。該模塊主要實現兩個目標:
- 為不同的外部系統提供多元化的接入機制。
- 通過數據適配的手段把外部數據以統一的格式進行轉換和存儲。
在數據接入層,我們會針對不同的數據接入方提供三種不同的數據接入模式。
- 數據拉取:我們主動拉取數據,并通過數據適配的方式,將數據存儲到對賬數據池中。
- 數據推送:由數據接入方將數據通過ETL(Extract-Transform-Load)等方式直接推送到我們的對賬數據池中,數據格式由數據接入方自行適配。
- 文件上傳:我們會提供標準的文件模板,由數據接入方填充數據,通過文件上傳的方式將數據接入到我們的數據池。
其中第二種方式是我們最優選擇的,因為數據推送這種形式對于數據接入方來說只需要一次性編寫相關的代碼,定期運行,一勞永逸,減少了人工上傳的成本。對于我們結算來說,也不需要感知對方的數據格式以及業務邏輯。
數據核對(軋賬)
數據核對是對賬中最核心的一個階段。其目標是發現問題數據。數據核對階段我們的兩個目標是保障數據核對的覆蓋度和準確性。經過總結和梳理,數據核對過程可以分為以下5個環節。
1. 問題梳理
由于數據核對的目標是發現問題,那么我們進行數據核對就要從問題出發,首先明確我們要通過對賬發現哪些問題,只有這樣才能保證數據核對的覆蓋度。經過梳理,我們發現在數據流轉中過程中數據的不一致問題可以統一歸結為三類,分別是漏結、重復結、錯結。我們可以從這三個角度去統一進行問題梳理。下面介紹一下這三種錯誤類型的具體含義。
- 漏結:發起方有數據,而接收方沒有數據。舉個例子,目前清結算系統會在訂單送達時給騎手結算。如果訂單的狀態是送達,而沒有給騎手生成對應的結算數據。就是一種典型的漏結算場景。
- 重復結:接收方重復處理。還是上面的例子,如果訂單送達,給騎手結算了兩次,產生了重復的結算數據,就是重復結算。
- 錯結:發起方和接受方數據不一致。一般會發生在金額和狀態兩個字段。比如說訂單上的數據是用戶加小費3元。結算這邊只產生了2元的小費結算數據,就是錯結。
2. 對賬方式
對賬方式主要分為兩種,單向對賬和雙向對賬。
- 單向對賬:以一方數據為基準進行對賬。比如結算跟支付平臺,以結算數據為基準和支付平臺核對,用來發現結算數據為支付成功,支付平臺支付失敗等問題。
- 雙向對賬:以雙方的數據互為基準對賬。既要保證結算數據為成功的,支付平臺也要成功,又要保證支付平臺數據為成功的,結算數據也要成功。
顯而易見,雙向對賬更能夠全面的發現問題。因此在條件允許的情況下,我們會優先選擇雙向對賬。
3. 對賬粒度
對賬粒度也分為兩種,分別是明細對賬和總數對賬。
- 明細對賬:對雙方的每條數據依次進行比對。它的優點是可以準確定位問題數據。缺點是對賬口徑的設計比較復雜。因為我們需要同時針對漏、重、錯三種錯誤類別設計不同的對賬口徑,同時還要考慮到業務的邊緣場景。稍有不慎,就會影響對賬的準確性。
- 總數對賬:選擇一個維度,進行總數級別的對賬。總數級別的對賬好處是對賬口徑的設計比較簡單,可以快速實現,不易出錯。缺點就是無法定位問題數據,一旦對賬發現問題。還需要進一步尋找問題數據。
因此,推薦的做法應該是以明細對賬為主,定位具體問題。以總數對賬為輔,對明細對賬的結果進行復核兜底。
4. 對賬口徑
對賬口徑,也就是具體的對賬邏輯的設計。我們會提供固定的對賬模板,供不同的對賬場景選取。如果某些特殊場景對賬模板不能覆蓋,也可以采取對賬邏輯自定義的方式進行對賬。
經過總結我們發現,對賬的形式無非就是兩方比對和自身異常檢測兩種。兩方比對又可以細分為一對一、多對一、一對多。比對方法也主要是分為條目匹配和金額匹配。自身異常檢測主要是重復性和異常狀態的檢測。我們把這些通用的對賬邏輯模板化,減少重復的開發工作。
5. 對賬時機
數據核對的最后一步就是對賬時機的選擇。分為離線對賬和在線對賬。離線對賬主要是通過固定的周期進行對賬。最短周期為T+1。它的好處是適用性較強,基本可以覆蓋所有的對賬場景。而在線對賬又分為實時對賬和準實時對賬。實時對賬和準實時對賬的區別主要是實時對賬耦合在結算鏈路中,可以在發現問題數據時,對結算流程進行攔截,而準實時對賬是異步進行的,不具備攔截能力。在線對賬有一定的局限性,一方面它依賴于對賬數據是否能實時的準備好,另一方面也比較占用系統資源。因此我們的做法應該是以周期對賬為主,在某些實時性要求比較高,且條件滿足的場景使用在線對賬。
差錯處理(平賬)
差錯處理主要是對數據核對過程中發現的問題數據進行處理。我們會建立一個統一結構的差錯記錄,將數據核對發現的問題進行統一存儲。差錯記錄中的數據會進行二次核對,避免由于日切等原因造成的問題錯報。對于那些真實存在問題的數據我們會提供兩種解決模式,如果是常見的問題,且有一套標準的解決方案的話,我們會把它系統化,采取系統自動修復的方式;如果系統無法自動修復,那么我們會進行系統報警,并進行人工處理。
對賬系統設計實現
總體架構
綜上所述,對賬體系的整體架構,分為三個模塊,分別是離線對賬平臺,在線對賬平臺和平賬中心。完全是按照我們上面的對賬思路設計的。三個模塊互相協作,一體化的完成數據準備、數據核對、問題處理三部分工作。由于我們整個清結算系統是圍繞不同的費用項建立的,因此費用項也是我們設計對賬、執行的對賬一個最小粒度的單元。
具體介紹下三個模塊:
離線對賬模塊
離線對賬分為三個子模塊,分別是數據接入層、對賬管理層和對賬執行層。
在數據接入層我們提供拉取和推送兩種模式,經歷一個數據適配的過程,將數據存儲到我們統一的對賬數據池當中。
在對賬管理層當中,我們抽象出了一個對賬場景的概念,我們基于對賬場景進行對賬屬性的配置:首先要選取對賬雙方的數據源;然后進行對賬口徑編輯,這里提供了自定義和模板選擇兩種方式;最后配置對賬的周期。這里我們是通過cron表達式來進行周期配置的。
在對賬執行層,我們會拉取對賬數據池和對賬核心配置中的相關數據,經歷配置解析,數據抽取,策略執行的過程,最終輸出對賬結果。
在線對賬模塊
下圖左邊是在線對賬平臺的架構圖,右邊是在線對賬的實例。我們通過RPC、監聽消息隊列(MQ)、監聽數據庫binlog三種方式進行對賬接入。在線對賬平臺分為管理層和執行層。管理層主要是承擔策略編輯、策略綁定和攔截管理的相關工作。而執行層分為異步(準實時)對賬和同步(實時)對賬兩個模塊。
右邊兩圖分別是分別是異步對賬和同步對賬的實例。在異步對賬的實例中,是運單和結算單元的對賬。
- 運單是什么?對應外賣訂單,作為配送內部的基礎交易數據。
- 結算單元是什么? 清結算系統內部的模型,和運單是一對一關系,記錄運單各個節點的結算狀態。
①異步對賬:我們分別監聽運單和結算單元的Binlog,通過Kafka->Storm的經典架構,進行對賬策略的執行。實際的流程比較復雜,這里只是一張簡圖,大概就是:(細節可以忽略)
收單運單消息后,我們會把對于的運單以List的形式存儲到Squirrel(Redis)中,當結算消息來了以后,就把對應運單記錄Delete掉。如果有運單記錄一直停留在List當中,也就是說明結算消息沒有來,應該是發生了漏結算。我們通過過定時任務輪詢運單List將問題數據輸出。
②同步對賬:示例中是結算內部的流程,經歷結算單、賬單、付款幾個流程。因為付款是最后一個流程,如果這個時候數據存在問題,那么就會造成實際的資金損失。因此我們會在付款環節之前,對前面的數據進行對賬。如果發現賬單和結算單的數據不一致,我們就會進行數據攔截。
差錯處理模塊
在差錯處理階段,我們會建立一個統一的差錯記錄模型,核心字段包括對賬場景、對賬批次,數據來源,錯誤類型編碼和數據處理狀態等。通過定時任務定期輪詢差錯記錄的方式發起差錯處理流程:首先對差錯記錄的數據進行二次核對,如果二次核對確認這條數據并沒有問題,我們就會回更差錯記錄的處理狀態。如果二次核對發現數據確實有問題。我們會提供兩種處理模式。一種是通過系統的手段自動修復。另外一種是通過報警的方式,人為介入。此外我們還建立了一個問題的人工處理模塊。可以對一次結算流程的整個生命周期進行回放,并針對特定場景提供一鍵修復的能力。
小結與展望
按照計劃實施后,系統的各個節點都會有行之有效的對賬手段覆蓋,實現資金安全、數據一致性的保障,示意圖:
本篇文章的內容是我們根據業務的特點,經過長期的思考和外部調研,總結的一套關于對賬的思路以及實施落地方法。目前我們對賬體系還在分布實施階段,我們最終的目標是:
- 覆蓋度:實現全鏈路無死角的對賬。
- 處理效率:對于問題的處理盡可能的去人工化,實現自動化或者工具化。
- 接入成本:后續新的業務場景實現對賬盡可能的降低成本。
目前外賣配送的單量與日劇增,資金安全所面臨的挑戰越來越大。需多次強調的是:資金安全是一個很大的課題,需要投入大量的時間和精力去系統思考,對賬只是其中一環。我們目前圍繞資金安全進行了一系列的治理動作,未來還將會繼續加強我們對于資金安全的理解深度,通過更多的對外交流和學習豐富我們保障資金安全的手段。
轉載于:https://www.cnblogs.com/davidwang456/articles/8744519.html
總結
以上是生活随笔為你收集整理的美团配送资金安全治理之对账体系建设的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一份平民化的应用性能优化检查列表(完整篇
- 下一篇: 问问大家作为大数据总监,刚刚到一家新单位