乾貨 | 多業務線億級體量,攜程是怎麼做賬務中臺的

{"type":"doc","content":[{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"一、前言"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"原先攜程內部的各賬務系統都是隨着自身的業務發展而建立起來的,其中有些共同的東西,但也存在着不少差異。但其對底層業務的抽象是統一的,都可以抽象爲:賬戶開立、記賬、稽覈。爲了系統開發、運維的簡便性,也爲了更好的爲前臺業務提供支持,我們計劃實施賬務中臺系統,從而做到賬務系統的:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1)"},{"type":"text","marks":[{"type":"strong"}],"text":"敏捷"},{"type":"text","text":":快速的適應業務需求的變化,滿足外部快速變化的需求,實現業務的敏捷。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2)"},{"type":"text","marks":[{"type":"strong"}],"text":"解耦"},{"type":"text","text":":建立功能獨立的系統,避免因爲一個功能的修改而影響很多方面,降低功能的耦合度。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"3)"},{"type":"text","marks":[{"type":"strong"}],"text":"複用"},{"type":"text","text":":對一些公共組件的複用,提高開發效率,避免重複建設,使得數據和流程都可以得到管控。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"二、賬務中臺之路-基礎篇"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2.1 系統概述"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"2.1.1 背景"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"賬務系統從2014年開始一期建設,先後經歷了兩次大的技術架構升級。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"一期:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"賬務組剛成立的時候,攜程的JAVA技術棧尚未完善。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"技術上我們是首批試點使用JAVA的小組,使用的分佈式RPC框架是Zeroc ICE,它可以支持多語言,通過slice文件生成代碼,性能也比較好,所以當初選型用了這個。消息隊列用的RABBITMQ,緩存用的REDIS。這些集羣都是自運維的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"業務上,一期的業務只支持單用戶單賬戶的模式,交易支持充值、支付、退款、預授權類(預授權凍結,預授權撤銷,預授權完成,預授權完成撤銷)、提現、轉賬,接口都是基於業務接口獨自開發的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"系統業務架構圖如下:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/29\/298ff091d5e544670a4d1fdbf2653d5e.jpeg","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"二期:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"隨着攜程JAVA技術棧的完善,二期主要針對JAVA技術棧進行了升級,放棄了自運維的集羣,使用了攜程JAVA體系,包括SOA,qconfig,qmq,qshecdule等技術。業務上增加了會計系統和日終的實現。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"系統業務架構圖如下:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/55\/55d7e412b4b8b134847cf92e48e79c00.jpeg","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"原有的賬務核心系統存在以下問題:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1)抽象不足:對業務規則抽象不夠,如果新增業務需要編碼實現"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2)隔離不夠:系統不同業務的系統流量、數據沒有隔離,存在某一業務有問題,影響全局的風險"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"3)降級策略:不支持"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"4)擴容困難"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"基於以上問題,我們設計並實現了新的統一賬務平臺。"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"2.1.2 目標"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"針對舊系統的不足,我們確定統一賬務平臺的目標:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1)抽象"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2)隔離"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"3)易擴容"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"4)配置化"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"5)支持多機構多幣種"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2.2 系統架構與簡介"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"統一賬務系統旨在建立一套立足於攜程集團之下的高可用,易擴展,業務可定製的賬務系統。系統包括場景碼系統,賬務前置系統,賬務核心系統,賬戶管理系統,會計系統,異步系統,job系統,日誌系統。各個系統之間通過dubbo進行服務拆分解耦。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"系統業務架構圖如下:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/6c\/6c017580dcdfd12a107181dc06b38e8a.jpeg","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"前置系統:賬務的業務處理系統,主要負責對上游業務系統的對接,完整賬戶的拆分等工作。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"賬務核心系統(原子系統):主要負責賬戶記賬,記錄對商戶、用戶、內部戶等客戶賬的動賬及明細。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"管理系統:對外提供商戶、用戶、內部戶的管理服務,包括創建、查詢、狀態凍結、狀態解凍等服務。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"會計系統:採用複式記賬法根據分錄規則對發生的交易進行記錄,來表示資金的流轉。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"基礎服務系統:對外提供科目、分錄、交易碼等基礎配置的查詢服務。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"日終系統:對記賬原子和會計系統數據進行稽覈,完成數據校驗工作。"}]}]}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2.3 系統設計"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"2.3.1 基礎組件設計"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"2.3.1.1 日誌組件"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們日誌進行logger輸出,會碰到以下的痛點:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1)我們經常會對方法的入參,出參及異常進行日誌打印,還要把tag寫入clog和ES,手寫的話工作量巨大。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2)有些日誌需要脫敏處理,比如手機號、身份證號、卡號,不能把明文輸出到日誌。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"3)logger目前只支持拋公司的logger日誌平臺,部門想自定義日誌查詢分析工具比較困難。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"所以在設計統一賬務中臺化的工程中,進行了日誌組件的設計:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1)統一使用高性能的log4j2替代logback;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2)通過spring aop和annotation,支持方法入參、出參、異常日誌的自動打印;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"3)支持clog和es的tag的配置,可以從參數中獲取,並通過log4j2的ThreadContext打入本地線程,線程使用過程中tag共享,代碼如下所示:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/90\/90fc1c78c06c1d567f10811c9c52a3f2.png","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"4)支持配置脫敏規則,進行敏感信息的脫敏處理;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"5)同步拋公司的clog和cat,異步拋kafka,異步接受程序進行ETL處理,拋部門自己的日誌系統(比如鷹眼系統,hive日誌分析系統);"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"6)拋kafka時,對於原始報文進行apache arvo壓縮處理,減少傳輸帶寬;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"7)支持原生API,可以手工打tag和脫敏處理。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"       "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"流程圖如下:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/bc\/bceb712817be5d8e71d87bbf8e6d4f92.jpeg","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"2.3.1.2 分庫分表組件"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"分庫組件,我們調研過公司現有的和開源的組件,最終選用了開源的sharding-jdbc。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1)攜程的dal組件"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"dal使用dal cluster通過服務端配置分庫分表信息,但是全套使用dal太過笨重,它是一個完全的ORM框架,生成sql的工具不支持生成特殊自定義的sql。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2)去哪兒的qdb組件"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通過配置表達式或算法的方式進行分庫分表配置,缺點是文檔較少,容易踩坑。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"3)MYCAT"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Mycat是一箇中間件,它攔截了用戶發送過來的SQL語句,首先對SQL語句做了一些特定的分析:如分片分析、路由分析、讀寫分離分析、緩存分析等,然後將此SQL發往後端的真實數據庫,並將返回的結果做適當的處理,最終再返回給用戶。Mycat的缺點就是需要搭建一套中間件做攔截者,而且需要自運維,成本比較高。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"4)sharding-jdbc"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"噹噹網首先推出的開源分庫組件,現在變成apache項目,分爲sharding-jdbc、sharding-proxy。開源社區活躍。我們使用輕量級的sharding-jdbc,可以編寫算法,支持精確分片、範圍分片、複合分片和自定義hint分片,配置方式支持xml、yml和java api方式。基本能解決我們所有的分庫分表需求。我們把分庫算法包成jar包,方便使用。配置我們使用yml。在使用過程中,需要結合dal cluster的key,代碼示例如下:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/14\/14eed01148e1c9024c98105efb7a6232.png","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"2.3.2 前置系統設計"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"賬務前置位於整個賬務體系的最上游,提供標準的交易接口,包括入款、入款返還、出款、出款返還、預授權類、轉賬以及批量接口。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"2.3.2.1 標準的交易接口"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"整合之前的老系統,都是業務導向的接口,隨着業務的不斷迭代,接口越來越多,職責不清晰,代碼重複,給維護帶來很大的工作量。比如:光提現接口,就分爲個人提現、返現提現、商戶提現和定向提現。另外,原先的子賬戶的交易順序是硬編碼的,如果發生子賬戶的增加或交易順序的變化,帶來的複雜度就成倍增加。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們經過研究,發現賬務處理是有共性的,對於交易順序、原子交易類型都是可以提取出屬性的。所以我們建立了場景碼模型。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"首先,我們定義子賬戶id,按賬戶類型+幣種+業務類型唯一定義一個子賬戶。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"其次,按產品代碼+交易類型來定義一個交易順序,交易順序關聯子賬戶id,該順序設置爲默認的場景碼。接口只要傳入產品代碼和交易類型就能能走默認的場景碼。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第三,支持商戶自定義場景碼,我們維護了一個後臺管理系統,允許商戶自定義場景碼,審覈通過後,接口傳入該場景碼編號就可以走自己定義的場景碼。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"2.3.2.2 異步化"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們接口都是同步接口,爲了減少同步響應時間,把次要的工作通過mq進行異步化處理。比如:轉賬的轉入方入款,拋送會計等。 "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"2.3.2.3 數據庫策略"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"除了支持自己的支付業務,也支持把賬務系統輸出到其他BU。爲了數據權限及互不影響,我們做了數據隔離。需要特別說明的是,只做數據隔離,系統還用同一套,不做隔離,方便發佈和運維。數據隔離分兩層,第一層是domain,區分自有\/BU。第二層是具體分庫。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"sharding庫也分兩套,Mapping庫和交易庫。Mapping庫存放請求流水號和前置流水號的關係。交易庫存放所有的交易信息。特別地,我們把逆向交易和原交易落在同一DB中,這樣有利於控制逆交易和原交易在一個事物內。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"首先,我們使用請求流水號做hash算法,分散到mapping db。Mapping db只保存請求流水號和前置流水號的關係,Mapping db也是分庫的,分庫數量初始是固定的,以後擴展可以用一致性hash算法進行擴容。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們的交易表是通過權重配置來分庫,通過權重可以進行數據的自由分配。DB支持友好的擴容,下線和故障切換。我們有一套故障切換的方案,如果某個分片出現dbconnect異常,我們會拋送支付的監控系統。監控系統會有套智能算法會實時監控,達到閥值後自動觸發該分片的markdown\/markup機制。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"2.3.2.4 異常處理"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"高併發場景下的異常處理一直都是各方研究的課題。爲了適應高併發場景,前置做了如下的異常處理:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1)冪等機制:所有接口都支持冪等操作。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2)重試機制:接口內部調用的重試,job補償重試,上游也可以發起相同請求報文的失敗重試。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"3)查詢機制:所有接口都寫了一套查詢接口,上游可通過查詢接口查該交易的最終狀態。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"4)通知機制:支持成功\/失敗的結果主動通知上游的機制。"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"2.3.3 原子系統設計"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"原子系統流程處理中,主要有以下幾步:訂單參數預處理,分單,同步執行器,異步執行器,後處理,最後封裝參數返回。爲方便業務擴展,系統維護,在分單和執行部分,系統架構採用責任鏈模式的分單器;代理進行分單,產生drivers,再由系統自動註冊的同步執行器和異步執行器進行執行。目前,只有訂單登記簿採用異步方式完成,後續job系統中會對任務進行相應的補償。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下圖爲原子系統的系統架構圖:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/16\/16f767179fd6bfc8a840321f3a957f1b.png","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"PreBizProcess是參數預處理部分根據調用域不同進行了定製化校驗與信息構造。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"DispatcerControl是分單部分,因爲原子系統負責賬戶餘額的管理,不存在任何業務邏輯,所以可以將記賬模型進行抽象以適應不同的業務需求。記賬模型包括賬戶入賬與出賬(Accnt)、活動入賬與出賬(Activity)、資金凍結與解凍(Fund)、日登記簿入賬與出賬(DaliyBook)、訂單登記入賬與出賬(OrderBook)等記賬模型。針對有效期概念的賬戶,增加了登記簿管理,日登記簿對賬戶同一有效期的資金進行彙總,訂單登記簿是有效期的資金的訂單維度的記錄。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"SynExecutor是同步執行器主要負責出賬入賬,資金凍結解凍,日登記簿處理;AsynExecutor是異步執行器負責訂單登記簿的記賬操作。日登記簿採用同步執行的方式,而日登記簿記賬成功可保證訂單登記簿記賬成功,故訂單登記簿採用異步記賬既可以保證記賬成功又能減少系統同步處理的時間。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"後處理部分會發送動賬消息,給關心賬戶餘額變動的系統,比如風控。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/51\/511995babca4996a1f180b7b35e40589.png","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"2.3.4 會計系統設計"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"會計系統採用複式記賬方式完成,可以清晰的表述資金是從哪裏來並流向了哪裏,針對不同的業務涉及不同的清分規則。在清分規則中可以配置記賬的不同策略,比如單條、彙總記賬等不同策略。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"針對同一業務多科目的場景,添加擴展配置,實現清分規則的科目動態化。"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"2.3.5 日終系統設計"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"2.3.5.1 爲什麼需要日終系統"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1)提供賬務系統支撐"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"要保證賬務系統能正常運轉,賬務的餘額要100%準確。影響賬務系統穩定性的主要因素有一下幾個方面:"}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"緩衝記賬,問題表現:分錄有數據,明細無數據"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"會計異步記賬,問題表現:明細有數據,分錄無數據"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"分錄規則配置,問題表現:同一筆分錄中,借貸方金額不一致"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2)爲企業大財務提供彙總記賬憑證"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"賬務系統記錄的是業務賬,這些數據是整個企業財務數據的一部分,需要合併到公司的大財務系統中去。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"日終系統對會計分錄進行加工映射爲大財務的分錄,然後彙總,直接對接企業ERP總賬。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"2.3.5.2 日終系統都做了什麼"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/64\/646efa789758c8a784ede53928707bb5.png","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1)生成快照"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"每日凌晨統計截至上一日的所有賬戶的快照。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2)生成分戶賬"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"根據快照生成分戶賬。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"3)生成總賬"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"根據分錄流水生成科目總賬,科目發生額和餘額從末級科目逐級彙總到一級科目。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"4)總賬平衡檢查"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"餘額平衡檢查:一級借方科目餘額=一級貸方科目餘額;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"發生額平衡檢查:一級科目借方發生額=一級科目貸方發生額"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"5)總分覈對"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"總賬科目餘額等於分戶賬科目餘額。業務24小時不間斷運行,賬戶中餘額在不斷變化,無法準確取到期末的賬戶餘額進行覈對,採用餘額快照與總賬科目餘額進行覈對。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"6)稽覈明細"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"檢查明細賬與分錄流水是否一致。對於當日發生過餘額變動的賬戶,昨日餘額與分錄流水中的發生額進行軋差,檢查計算出的餘額與快照餘額是否一致。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"2.3.5.3 日終系統遇到的挑戰"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1)24小時記賬"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在銀行賬務系統中,對於24小時運行,有很多種方案,例如切換餘額、記不同分戶賬、日切後補流水等,但無論哪種方案,都不能實現完全24小時運行。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"其問題,主要是因爲日終要進行總分覈對,而分戶賬餘額是在不斷變化的,所以要想辦法把期末的分戶賬餘額取出來進行覈對。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本日終系統解決方案,採用餘額快照與總賬進行覈對,這樣即使分戶賬餘額進行變化,也不影響總分覈對。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2)生成賬戶快照"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"生成快照的方式有兩種:"}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"從賬戶餘額中獲取"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"交易明細按賬戶彙總發生額更新快照"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"相較於數億賬戶而言,每日發生交易的則要少得多。採用動賬彙總的方式,對於數據庫的操作更少,處理時間更快。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":"br"}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"3)流程複雜、測試困難"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/26\/26fb1e5fe172f2ba63dd122d0b8d10fb.png","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對日終任務模型進行抽象,按照業務邊界劃分爲:快照生成、分戶賬生成、總賬生成等多個子任務,自動註冊到任務工廠中,以便編排調用。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2.4 總結"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"此係統業務接入規則、會計清分規則都是基於配置的,在業務發展的新增賬戶類型、業務、幣種、機構等日常變化都可以基於配置進行。          "}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"三、後記"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"賬務中臺建設到現在,已經完成了攜程體系內賬務中臺的基本建設,這只是中臺建設的第一步,後續規劃還包括分佈式事務、熱點賬戶的處理;新機構業務接入如何更簡潔等等。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"作者簡介"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本文爲聯合撰文,作者團隊負責攜程集團支付賬務系統、消費金融賬務系統、清結算和對賬等工作的的開發、設計和運維工作。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本文轉載自:攜程技術中心(ID:ctriptech)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"原文鏈接:"},{"type":"link","attrs":{"href":"https:\/\/mp.weixin.qq.com\/s\/PigndZkDuJgq7Mj_M3-S_A","title":"xxx","type":null},"content":[{"type":"text","text":"乾貨 | 多業務線億級體量,攜程是怎麼做賬務中臺的"}]}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章