支付系統如何進行分散式改造
原創宣告 :本文系作者原創,謝絕個人、媒體、公眾號或網站 未經授權 轉載,違者追究其法律責任。
傳統支付系統面臨的挑戰
隨著近年來移動支付的興起 ,如條碼支付、聲波支付、NFC 近場支付等,隨之還產生了聚合支付把多種支付方式聚合在一起,方便人們的使用,移動支付已經滲透到我們生活的每一個角落,不帶錢包出門已經沒有任何阻礙。這就給傳統的支付系統提出了新的挑戰,使用者量激增,系統容量和效能跟不上了,傳統的架構往往以 IOE 技術為主,採用 scale up 方式以更強的硬體提升系統性能和容量,擴容成本將是巨大的。支付機構是持牌機構都是受監管的,對系統穩定性有強要求,傳統架構下往往都會用冷備的方式來進行容災,意味著又要投入一倍的成本,由於資料庫主備複製的延時,必須等到資料同步完成才可以切換,容災切換時間長。進行分散式改造已經刻不容緩。
更多關於傳統架構與分散式架構對比請參考《 集中式架構與分散式架構比較 》
分散式架構在容量、效能、穩定性、成本方面都具有巨大的優勢。在高可用方面,核心思想之一是“解決一切單點”,單點容易出現故障,效能方面也可能成為瓶頸,因此需要將單點改造拆分成多個點。垂直拆分能更清晰化模組劃分,區分治理,水平切分能解決大資料量效能瓶頸問題,分散式改造主要是將這兩者結合起來,對傳統架構進行全面的改造。
分散式改造之垂直拆分
垂直拆分就是將原來一個整體的系統按業務模組拆分成多個系統,系統內部資料是自包含的,不會與別的系統共用資料庫,系統與系統之間的互動通過暴露和呼叫服務來實現。那麼如何按照業務來拆分呢?
為了方便理解,首先我們來看一下一筆支付過程是如何進行的:
-
商戶發起收單請求,經過 API 閘道器,調到產品層的“線上收單”產品
-
呼叫收銀臺選擇支付方式,也可能直接進入支付環節,建立交易流水
-
進行支付處理,通過金融交換從銀行扣客戶帳,記錄帳務流水,入商戶帳,記錄賬務流水
-
對交易按照費率進行收費,記錄收費的帳務流水。此時會非同步觸發營銷和風控策略
-
日終會非同步進行會計記帳(也有同步記會計帳的)、業會核對、清結算和對帳處理
從這個過程可以大概推演出支付系統的一般應用架構 :
圖:支付系統的應用架構
應用架構定義一個大型軟體系統由哪些應用子系統構成,以及應用之間是如何分工和協作的。好的應用架構抽象合理、協作有序、易於擴充套件、能夠複用。有了這個應用架構,我們就可以非常清晰的根據應用架構劃分的子系統來進行垂直拆分。
從架構上來說,分為四層:
圖:支付系統的分層
渠道層 : 商戶和客戶的交易請求的入口。一般會劃分以下系統:商戶網站、使用者網站、無線接入、API 閘道器。
產品層 : 通過基礎服務層提供的服務組裝成具體業務場景功能,對客戶、商戶運營等人員提供服務。一般會把服務商戶的功能劃分為商戶域,服務 C 端使用者的劃分為使用者域。可以按照這兩個域拆分成兩個子系統,也可以更進一步根據不同產品特性再拆分,比如商戶域中的收單產品、虛擬產品、垂直行業產品。
公共服務層 : 將各個產品都需要使用的些服務抽像成公共服務。一般會劃分:收銀臺、交易支付、計費等系統。比如說產品層可以通過組裝各種交易型別和收費規則形成不同的產品。
基礎業務層 : 支付系統的核心,資金和客戶資訊的處理都在這裡。一般會劃分三大子系統:帳務核心、會計核心、會員核心。
其它支撐系統 :
閘道器 : 負責與銀行、銀聯等金融機構進行資金交換,與外部合作伙伴接入,如渠道拓展商、行業客戶等。一般劃分:銀行接入閘道器和合作夥伴接入閘道器。
運營支撐 : 貫穿於四個層的是運營支撐域:一般會劃分運營支撐、安全、風控、營銷子系統。
垂直拆分本質上是服務化改造,除了上面講的按業務拆分,還需要一套分散式服務框架的支撐。
分散式改造之水平拆分
前面講的垂直拆分只是把系統按業務模組劃分到不同的子系統,資料庫也分到了不同系統,但沒有解決單表大資料量的問題,而水平切分就是要把一個表按照某種規則把資料劃分到不同表或資料庫裡。簡單的說就是做分庫分表。
在做分庫分表之前我們需對資料模型進行分類,分為“流水型資料”、“狀態型資料”和“配置型資料”。
-
流水型資料 : 像流水一樣不斷增長的資料,各條資料間是獨立的。如支付訂單、交易流水、帳務流水(入帳/出帳)、會計流水等。
-
狀態型資料 : 代表一個物件當前的狀態的資料。如會員資訊、客戶資訊、帳戶資訊、會計帳。
為什麼有會員資訊還有客戶資訊?會員往往是註冊在支付平臺的使用者,一個人可以註冊多個會員,但是一個自然人只可能有一個客戶資訊,一個會員通過實名認證後就關聯上了客戶資訊。無論一個客戶註冊多少個會員,實名認證後都只有一個客戶資訊。
-
配置型資料 : 系統中用作為配置的資料。如產品、手續費率、分支機構資訊、支付路由規則、會計科目等。
流水型資料會不斷產生,且各條資料間是獨立的,天然適合進行分庫分表。
狀態型資料讀寫比相當,每一次寫操作必須基於前一個正確的狀態,可以評估一下資料量的大小,資料量如果大或者要實現單元化架構,也需要進行分庫分表,提高併發處理能力,同時方便隔離故障影響。
配置型資料,讀多寫少,強依賴讀,弱依賴寫,不要求嚴格的讀一致性,且配置型資料一般資料量不會很大,不需要進行分庫分表設計。但是業務處理中往往又需要用到,傳統架構的老系統可能使用了一些關聯表操作,關聯到了配置資料,分庫後其它資料與配置不在一個庫,不能進行關聯表操作, 由於配置型資料不要求嚴格的讀一致性的特點,可以將配置型資料載入到分散式快取裡,由業務程式碼來做“join” 。
那麼分庫分表按照什麼規則來拆分呢?通常不會按實體 id 進行 hash 取模的方式來拆分。因為希望同一個使用者的資料能夠在同一個資料庫中,儘量避免產生分散式事務。業界普遍的做法是通過使用者維度來進行拆分。由於不同實體 id 的值不同,且不能保證每個實體和請求中都包含使用者 id,所以簡單的用實體 id 或使用者 id 進行 hash 取模將不能保證同一個使用者的資料都落在同一個分片。
一種推薦做法是,在使用者建立的時候給該使用者隨機或一定規則(如地區)生成一個兩位的分片號 00~99(兩位意味著可以分成百庫百表,通常夠用了),那麼在生成與該使用者相關的所有實體的 id 的時候,都約定把這個分片號拼接到這個 id 中。在分散式資料訪問框架中進行路由選擇時,就可以取 id 中的分片號進行路由,而不依賴於使用者 id。且在排查問題的時候也非常方便定位資料的儲存位置。
下面是一個參考的 id 生成規則示例:
所以資料水平拆分除了需要一個強大的分庫分表資料訪問中介軟體,還需要一個分散式序列生成器。當然這個生成器也可以是整合在分庫分表資料訪問中介軟體中的一個功能。
那麼如果一筆交易涉及多個使用者按誰的 id 來拆分呢?比如一筆轉賬或支付,涉及轉出方/轉入方或支付方/收款商戶。這種情況一般可以按資金轉出方來拆分。
分散式改造後帶來的問題如何應對
分散式事務產生
由於按使用者維度進行了分庫分表,可能存在跨資料庫的事務,比如說,轉賬交易中轉出方和轉入方的賬戶不在同一個資料庫中,這就產生了分散式事務。通常不會用 XA 協議來解決,因為 XA 協議鎖資源效能太差,通常是通過 TCC 柔性事務來解決。具體可以參見進階閱讀《 分散式事務綜述 》。
跨表查詢如何解決
由於分庫分表後,不能進行跨庫的連表查詢,原來的一些很常見的查詢操作變得很麻煩。對於不是以使用者為維度的彙總查詢也非常麻煩。比如說支付交易流水是按發起方使用者(支付方)進行拆分的,使用者需要查詢自己的賬單很容易。但是商戶要查詢賬單就比較麻煩了,要去所有的庫裡遍歷、彙總、分頁。也非常耗系統資源。所以一般會做一些資料冗餘,例如專門實現一個賬單系統,通過訊息佇列非同步將使用者的交易流水同步過來,T+1 跑批再按商戶維度進行拆分,並生成商戶賬單。查詢帳單都從帳單系統中查詢。
還可以通過異構索引來查詢和做 OLAP 分析,異構索引就是將資料同步到 ElasticSearch,利用 ES 的強大索引能力來做查詢和分析,為了使業務更容易使用,可以利用資料訪問代理層來遮蔽底層是路由到資料庫還是路由到 ES。
如何進行資料同步
企業都有做大資料分析的需求,需要將資料同步大資料平臺,如 Hadoop。分庫分表之後,資料同步會比較複雜,畢竟之前是單表同步到 Hadoop 比較簡單,但是 100 張表同步到 Hadoop 裡會複雜一些。這時就需要設計一套專門的資料模型管理平臺,資料模型、分庫分表規則等由這個平臺來管理,當需要使用資料的時候通過(應用/邏輯表)維度訂閱資料即可,不用單獨訂閱物理表。不僅是資料同步,凡是有業務需要用到各種資料,都可以通過這個平臺來訂閱,幫助企業資料業務快速發展。
分庫分表後批處理任務怎麼處理
批處理任務,比如有日終對賬、清算、生成賬單等,原來在一個數據庫中的時候,由一個應用 Server 去資料庫中撈取流水就可以了。但是分庫分表後流水都落在很多庫裡,一個 Server 去每個庫裡遍歷顯然不是一個很好的辦法,且不能充分利用機器資源,提高批處理效率,甚至由於處理的資料量太大在日終低峰期內根本無法完成任務。
前面提到各條流水資料之間沒有關聯的,完全可以併發的進行處理,每個 Server 撈取一個分片的資料進行處理。那麼就需要有一個很好的排程系統來協調,可以採用三層排程的方式。
圖:三層排程示意圖
-
第一層 split:把任務按照分片規則拆分成多個 Load 任務,併發送到叢集中的 Server 去執行。
-
第二層 load:每個 load 任務撈取一個分片的資料,逐條建立 execute 任務,併發送到叢集中的 Server 去執行。注意:撈取資料要進行流量控制以免資料量太大把叢集打滿。
-
第三層 execute:執行具體的一條資料的邏輯。
三層架構並不是說一定都需要三層,可以根據業務邏輯來定製只有兩層也可以。
如何進行資料擴容
通常可以採用“預分配”的方式來做,即一開始就按一個比較長期的容量來規劃分片數,比如百庫百表。但實際上一開始並沒有這麼大的量,所以實際只有兩個資料庫 Server,在這兩個 Server 上分別建 50 個 schema,邏輯上仍然是 100 個分庫,物理上只有 2 個數據庫 Server。當容量不夠的時候,為了保證資料的均衡,通常會採用成倍擴容的方式,再加兩臺資料庫 Server,然後分別遷移 25 個 schema 到這兩個資料庫 Server 上,資料也搬過來。由於資料同步有延時,全量資料同步完成後,兩邊的 schema 都禁寫,待增量資料同步完成後開啟新的 schema 寫,會產生短暫的部分使用者交易失敗,重試一下即可,在低峰期做遷移,產生小範圍失敗一般是可以接受的。由於邏輯分片數沒有變化,擴容成本比較低。通常不會用改變分片規則的方式來擴容,因為改變分片規則需要進行資料重新分佈,成本和風險巨大。
如何進行容災
-
同城容災 :通常可以同城多機房部署應用,資料庫只有一個機房處於 Active 狀態,所有機房的應用都連這個機房的資料庫,另一個機房的資料庫為備庫,進行主備複製,當備機房發生災難時業務不會中斷,但業務會跌一半,當主機房發生災難時,資料庫切換備庫,會有短暫的業務中斷。
-
異地冷備 :應用也是異地多機房部署,由於異地網路延時不可忽略,異地備機房是處於 standby 狀態,正常是沒有流量的,冷備機房採用資料庫主備同步的方式同步資料,這種方式災備切換時間長,成本投入高。
-
異地多活 :應用採用異地多機房單元化部署架構,每個機房的應用都是可以提供服務的,單元內是自包含部署全量應用,每個單元服務多個分片的使用者,單元化架構可以參考《素描單元化》。由於異地網路延時是不可忽略的,資料層的容災方案也是分“流水型”、“狀態型”、“配置型”資料採用不同的容災策略。具體可參考《 分散式系統資料層設計模式 》。
如何更好的排查和分析問題
分散式改造後整個系統架構已經是服務化了,原來通常可以通過查本地日誌來定位問題。但現在一個交易由若干個系統協同完成,我們需要一套分散式鏈路跟蹤系統或 APM(應用效能管理)系統來協助我們看清整個系統的全貌,分析排查問題。那麼如何進行分散式鏈路跟蹤呢?可以通過 OpenTracing 標準對整個分散式架構中的中介軟體和應用進行埋點或自動植入探針實現。
總 結
分散式架構有著海量、成本、穩定、速度的優勢,但它也不是銀彈,分散式改造是一個較為複雜的工程,既需要熟悉業務,能夠設計出整個系統的業務架構,按照業務架構來進行垂直拆分,又需要熟悉資料模型,區分“流水型”、“狀態型”、“配置型”資料,根據不同型別資料的特點將它他按使用者維度進行拆分,還需要熟悉分散式中介軟體的運用。分散式中介軟體在整個分散式架構中起著至關重要的作用,將技術構架與業務結合起來。螞蟻金服通過多年金融級架構的演進,經過多年雙十一大促的驗證,已經形成了一套業界領先的金融級分散式架構, 請參考《 金融級分散式交易的技術路徑 》。
相關熱文


長按二維碼關注我們 ▶▶▶
點選【閱讀原文】獲取招聘資訊或傳送簡歷到 [email protected],期待您的加入!