天天看點

支付系統如何進行分布式改造

原創聲明:本文系作者原創,謝絕個人、媒體、公衆号或網站未經授權轉載,違者追究其法律責任。

傳統支付系統面臨的挑戰

随着近年來移動支付的興起 ,如條碼支付、聲波支付、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 标準對整個分布式架構中的中間件和應用進行埋點或自動植入探針實作。

總 結

分布式架構有着海量、成本、穩定、速度的優勢,但它也不是銀彈,分布式改造是一個較為複雜的工程,既需要熟悉業務,能夠設計出整個系統的業務架構,按照業務架構來進行垂直拆分,又需要熟悉資料模型,區分“流水型”、“狀态型”、“配置型”資料,根據不同類型資料的特點将它他按使用者次元進行拆分,還需要熟悉分布式中間件的運用。分布式中間件在整個分布式架構中起着至關重要的作用,将技術構架與業務結合起來。螞蟻金服通過多年金融級架構的演進,經過多年雙十一大促的驗證,已經形成了一套業界領先的金融級分布式架構,請參考《金融級分布式交易的技術路徑》。