20191216 支付中心架構設計方案

架構設計思考:

1)大型網站架構5大核心要素,這些如何保證?

2)內部包含哪些模塊,模塊之間如何拆分、如何通訊?(核心層,基礎支撐層)。

3)其他業務系統如何接入當前設計?單體服務,微服務,前端各個業務系統。

4)一切脫離業務的設計都是在耍流氓,所有的設計都必須從業務出發。

5)常用的架構模式有哪些?

6)每個小的功能模塊如何實現?技術上的實現細節。

7)表與表之間的映射關係,比如一對一映射,還是一對多映射,不涉及細節字段。

8)各個模塊之間,業務如何流轉?

支付中心技術方案設計

1、包含哪些微服務(內容邊界)

2、每個微服務有哪些接口功能 ( 功能邊界 )

3、服務之間的調用關係;服務之間如何通訊Https還是Feign;下單流程在微服務端如何流轉。

4、數據結構設計:E-R 之間的關係,表與表之間的對應關係。

 

大型網站架構要素之數據安全

1)外網使用https協議傳輸數據,在網關層校驗;內網之間使用http協議;

2)RAS+AES加密傳輸數據,這兩種方案第一種可能更好一些,

Http協議與https協議

1)網絡耗時增加;協議交互所增加的網絡 RTT(round trip time)。

2)計算耗時增加;加解密相關的計算耗時。

HTTP協議需要三次握手,目的是建立TCP連接

用戶只需要完成 TCP 三次握手,建立 TCP 連接, 就能夠直接發送 HTTP 請求獲取應用層數據。

 

代碼CodeReview

使用Gitlab的Merge Request實現

 

Redis與Mysql的不同

1)mysql多線程,redis單線程;

2)mysql讀寫分離,主庫負責寫,從庫負責讀;但是redis讀寫都在主節點,從結點只負責數據備份,當主節點掛掉後,從結點升級爲主節點才能進行讀寫。

3)redis多個主節點組成一個集羣,每個節點都是哈希環中的一部分。

 

分佈式job系統的使用

1)job配置中端口號寫錯了,還是沒有在三個線下環境測試通過;

2)xxlJobConfiguration的添加;(忘記了)

 

全局緩存設計

1)本地緩存+遠程分佈式緩存

2)不使用本地緩存框架(Cache),直接使用一個本地變量存儲本地緩存,有時候這種方式頁可以解決問題;

 

 

業務核心生命週期(下單--->支付--->財務管理),非核心生命週期的拆分(風控,數據安全)

空間上拆分業務模塊,時間上串行功能模塊;模塊與模塊之間低耦合。

各個功能模塊之間如何通訊交互?支付模塊本身如何進行拆分,提供一個接口還是兩個接口?

 

自己維護jar包,不斷地完善當前jar包的內容。

jar包內容:Swagger, 分頁工具類, pica響應類型、全局異常設計信息。

 

方案設計:微服務之間的依賴關係和層級關係圖,這個特別重要。

app------>交易中心--------->各種微服務<---------管理系統

 

驗證碼驗證的操作 在分佈式狀態下(高併發狀態下),如何保證原子性?

直接刪除key或者使用decr命令,都是原子操作;

 

組件模式:每個第三方支付,都有自己的一套對外 API,官方都有一套 SDK 來實現這些 API,我們應該如何組織這些 API 呢?由於第三方支付渠道會隨着業務的發展變動,所以組織這些 SDK 就需要在不影響支付平臺整體架構的前提下可靈活插拔。這裏我使用了組件的思想,將支付 API 拆分成各種組件支付組件、退款組件、訂單組件、賬單組件等等。

組件模式如何落實到代碼上?

 

根據場景來給出解決方案: 根據業務場景來給出數據一致性的解決方案。

三大理論:ACID事務特性,CAP分佈式理論,以及BASE等,ACID在數據庫事務中體現,CAP和BASE則是分佈式事務的理論。

A(原子性)事務的原子操作單元,對數據的修改,要麼全部執行,要麼全部不執行;

C(一致性)在事務開始和完成時,數據必須保持一致狀態,相關的數據規則必須應用於事務的修改,以保證數據的完整性,事務結束時,所有的內部數據結構必須正確;

I(隔離性)保證事務不受外部併發操作的獨立環境執行;

D(持久性)事務完成之後,對於數據的修改是永久的,即使系統出現故障也能夠保持;

 

從哪些角度去對比兩個項目?

大型軟件架構五要素,功能,接口,表設計,管理後臺、存在問題。

 

接口業務邏輯

業務系統----->支付中心----->第三方支付平臺

商品後臺管理系統:商品添加------>商品審覈------>商品上架等

服務之間的調用關係: 業務系統------>網關層(聚合層,門面模式)------>(商品服務、訂單服務、支付服務)

時序圖:購買流程時序圖,退款流程時序圖;

 

架構設計時:整個項目劃分爲哪幾層?包含哪些功能模塊,功能模塊之間的關係是什麼?

核心層,基礎支撐層。

業務系統如何與支付中心進行交互? 交互流程圖。

商品、訂單、支付方案設計:

1、現狀和設計目標

2、功能邊界:拆分成多個子系統,每個子系統完成什麼功能?

3、架構設計

4、功能技術實現(概要設計,不一定直接對等;使用哪些技術,接口流程是什麼?異常邏輯全部畫出來,很多情況下都缺少異常邏輯)

5、表設計以及接口定義

1)詳細設計,使用哪種設計模式屬於詳細設計;

2)接口方法名,入參出參;

3)表名定義和字段定義;每個服務包含哪些功能,每個功能涉及哪些表?

6、項目排期

 

注意:

1)是否需要異步進行日誌的記錄?

2)熟悉業務以及對應功能的技術實現。

3)異常流程全部補齊。異常流程特別重要,全部補齊。 一般都會缺少異常流程。

db+redis+mq+鎖機制。樂觀鎖+重試機制。

數據如何落庫?數據什麼時機寫入緩存,緩存哪些內容?如何發送mq消息?如何使用樂觀鎖?

 

支付中心拿到支付結果後如何通知業務系統?

1)支付結果數據落庫,並設置發送標記;

2)發送消息成功,修改發送標記;

3)如果發送消息失敗跑定時任務進行重複發送消息;

不能讓業務系統提供接口供我們直接調用,這樣支付中心和業務系統的藕合就太嚴重了,支付中心應該是完全獨立的服務。

 

訂單設計:

1、多筆支付,是否允許拆開訂單?訂單主表,訂單項表;按照什麼規則進行拆分訂單?

2、同件商品只能購買一次,如何防止重複下單(把庫存刷完,下單前先檢查一遍當前用戶的訂單裏是否有指定的商品id,如果存在就不允許購買)?

3、價格計算:是否使用優惠券,優惠券總金額以及現金總金額;

4、下單前進行庫存校驗,是否還有庫存;取消訂單時需要釋放庫存;申請退款後也需要釋放庫存。

5、訂單信息:商品信息、用戶信息、金額信息、下單狀況。

6、訂單號或者訂單表中設置訂單類型標識,當前訂單購買的商品類型以及訂單的業務線來源。

7、取消訂單:訂單自動取消和訂單超時取消。訂單狀態:待支付,已支付,已取消/關閉(超時取消,主動取消),已完成,退款中,已退款,已關閉。

商品價格修改,請重新提交訂單。價格校驗。 價格變動了,請重新下單。

訂單服務表設計

訂單主表:訂單id,買家id,名稱,電話,訂單狀態,總金額,創建時間,更新時間;

訂單詳情表:詳情id,訂單id,商品id,商品名稱,商品原價,優惠價,商品數量,備註信息,訂單來源。

 

數據庫關係圖 (數據表關係圖) (一般都是次表存儲主表的id)

表之間的引用關係。

庫存表----->商品表,庫存表是掛在商品表下面的。

退款表----->支付表----->訂單表;對某個訂單進行支付,表與表之間的關聯關係,多理解業務才行。退款表用於記錄退款信息。

外鍵指向主鍵。

表之間是否可以合併?把公共字段抽取出來,比如把微信支付和支付寶支付的功能夠用

商品表和庫存表映射關係

庫存表掛在商品表下面。 表與表之間的主次關係,由商品表延伸出主次表。 所以商品表是主表,庫存表是次表,一般都是次表存儲主表的id。

 

有限狀態機:表示有限個狀態以及在這些狀態之間的轉移和動作等行爲的數學模型

狀態機可以描述核心業務規則,核心業務內容;通常用於業務複雜的訂單等業務裏。

爲什麼要用到狀態機呢,用狀態機的好處是什麼?

一些複雜的業務流程使用。配合樂觀鎖使用。 狀態之間的變更和流轉。

訂單狀態機:只有上一個狀態確定時,才能更新當前狀態,要使用樂觀鎖機制。

 

如何進行方案設計

一個好的系統或者好的設計不是一開始被大牛設計出來的,一定是隨着發展和演進逐漸被迭代出來的。(逐漸迭代出來的)

整體方案如何?整體上和其他業務系統如何交互的,內部如何實現的(不能是黑盒)?

你用mq了麼?redis用了麼?鎖機制用了麼?

 

餓了麼:業務井噴時,訂單系統架構這樣演進

交易架構相關的工作,每種業務的架構類型都不一樣。

脫離具體的場景所有架構演進沒有任何意義。架構要結合業務場景設計,當前業務有哪些特點,是否需要高併發、高負載?

比如說監控、日誌、告警、框架、消息、數據庫,很多基礎設施還在建設之中。在這個過程中出現一些問題是在所難免的,對系統的要求不是不能掛、不能出問題,而是出了問題要第一時間能恢復。這是整個系統架構的前提。

存在問題:業務邏輯嚴重耦合;代碼管理很困難;因爲數據庫都在一起,操作變更很難追溯;性能的瓶頸只能是靠服務器去硬抗(堆積服務器);

演進工作的核心就是一個字“拆”,跟“拆”對等的就是分治的思想。怎麼拆分呢?面向服務有很多拆分原則。

 

第一是明確的定義。我們需要更明確,什麼纔算是一個服務?服務一定具有非常獨立的技術能力或者業務能力,而且一定意義上能夠很抽象。(獨立的技術能力和獨立的業務能力)

第二是鬆耦合。時間上的鬆耦合或者位置上的鬆耦合,我們希望的鬆耦合是消費方和服務方是可以分離的。(時間上的鬆耦合和位置上的鬆耦合)

第三是基於領域的認知。因爲當時整個餓了麼所有系統是在一起的,基於領域的認知,在面向用戶的維度和麪向商戶的維度做了切分,還有基於交易鏈路做了切分。(基於對領域的認知,領域模型麼?)

第四是單一職責和關注分離。我們希望一個服務或者一個模塊擁有單一的能力,而不是承擔過多的職責,否則責任不清晰,導致能力也不清晰。賬戶中臺就只負責和用戶登陸有關的業務。

最後一點是可被驗證的結果。當時認爲這樣拆分是沒有問題的,但是過一、兩個月,並沒有帶來效率和能力的提升,反而是跨團隊的要求越來越多,能力要求也越來越多。這時候可能是拆錯了。如果是一個好的拆分一定有利於發展,拆分之後的發展是更迅速的。(驗證前面的猜想是正確的)

 

一個接口有一個非常明確的Owner,一個表、一個庫也能保證僅有單一的操作方,讓我感受比較直接的是,爲服務的治理奠定了基礎,以後可以針對某項特定業務做一些降級、熔斷,以及單獨的監控。拆分實際上是讓各自模塊的掌控力變得更強了,對業務起到更好的支撐作用。(單一的操作方)

 

對於一些領域認知或者業務邊界的認識還是模糊的,沒有人界定這些。

 

首先要確認訂單到底在整個系統中,尤其是交易系統、O2O系統中承擔什麼角色,擔負什麼職責。

第一,訂單是整個交易鏈路的核心。圍繞了一些相關服務,比如金額計算服務、催單服務、售中異常服務等,我們希望這些服務之間有明確的區別。

第二,訂單實時處理是整個鏈路的中心。我們希望訂單核心流程非常簡單、輕薄,把複雜的東西剝離出來,把簡單和複雜明確成兩個部分。

第三,考慮到交易的時效性和異常場景越來越複雜,將交易分成正向交易流程和逆向交易流程兩個部分。正向交易流程,99%的訂單會根據這個流程走完生命週期;逆向交易流程,比如說退單要求時效性比較低,處理會牽扯多方業務可能很複雜,所以通過一個逆向的交易流程來解決。

第四,能夠在功能和業務上獨立的部分,儘可能抽象爲單獨的模塊或服務。(抽取獨立的模塊或服務)

架構:當前功能包含哪些模塊,模塊之間是如何分層的。

replicator 複製。

調用鏈路長:這是一個很大的問題,雲鵲醫機構通訊錄就是,響應慢,出了問題不好追蹤。

 

數據庫服務的演進。

dal是數據訪問層的英文縮寫,即爲數據訪問層(Data Access Layer)。其功能主要是負責數據庫的訪問。

引入DAL中間件做什麼呢?有幾個作用:數據庫管理和負載均衡以及讀寫分離,水平分表對用戶和商戶兩個維度做評估,爲用戶存儲至少半年以上的數據。解決了數據庫的瓶頸,系統整體負載能力提升了很多。和業務解耦,只有數據訪問層,或者說把數據訪問層做成一個獨立的服務。

數據庫服務:數據庫管理,負載均衡,讀寫分離等

DAL中間件起的作用,有讀寫分離端口、綁定主庫端口、水平分表、限流削峯以及負載均衡等功能。

系統瓶頸在哪裏? 業務系統那裏還是數據庫那裏。

 

監控和告警演進(系統指標,業務指標

通常我們重視系統指標,容易忽略業務指標;而其實業務指標更能反映出問題。有哪些業務指標?

過載保護和業務自動降級。

監控和告警的峯值非常明顯,午間和晚間兩個高峯,其他時間流量相對平緩。

 

把整個Service集羣做了分組,有面向用戶的、面向商戶的,還有物流和其他方面的。

 

第一是消息廣播補償,第二是主流程補償,第三是災備,第四是隨機故障測試系統。

主流程主要是針對鏈路本身出問題的情況,以最大程度保證交易的進行,也是對主要鏈路的保護。

https://www.cnblogs.com/best/p/8615535.html

 

 

訂單表存用戶id;支付表也存儲用戶id;

支付狀態:未支付,已支付,支付中。

聯合訂單主表表結構:訂單號,訂單總金額,子訂單類別(是否分期)

聯合支付訂單子表表結構:聯合訂單主表表id,子表訂單號,訂單類型。

 

主訂單表:訂單號,關聯的購買用戶,總金額。

訂單子表:子訂單id,主訂單id,買家id,商品id,購買商品當時價格,商品的數量,總價=優惠減免+實際支付金額,優惠減免,實際支付金額。

訂單表中應該有哪些字段?

策略模式 中的上下文環境(Context),其職責本來是隔離客戶端與策略類的耦合,讓客戶端完全與上下文環境溝通,無需關係具體策略。

 

狹義的支付系統,廣義的支付系統。

定義了支付系統包含哪些功能?

一個支付系統應提供支付渠道管理、支付網關、基本支付/退款/轉賬能力、支付記錄/明細,及其相關的監控運維繫統。至於所謂的賬務清算,對賬功能,賬戶體系,風控體系,現金流量管理,應納入到「財務系統」,也應該是大佬們談論的都是廣義的「支付系統」。

 

支付的流程包含了三大部分:發起支付,發起退款,接收回調。考慮到吞吐量的影響,將原先同步的編程方式改爲異步的編程方式,不出意外的話,將會使用到Java8的ExecutorService和CompletableFuture。

支付系統與業務系統解耦,並且把支付系統屬於基礎支撐業務中。

發起支付:客戶端和服務端如何配合完成一次支付請求。

發起支付架構圖

 

設置重試的次數(TaskInfo.retryTimes),默認三次,分別間隔1s,2s,3s,間隔時間以公差爲1的等差數列組成。當然不會讓用戶無限重試,系統內置有一個最大重試次數,最大重試次數內置爲5次。

默認重試次數,最大重試次數。

 

把支付參數封裝到一個模型裏面。公共請求參數。

直接使用long類型,支付系統的金額單位統一設置成人民幣【分】。

有的人一看不符合團隊的技術棧,直接就不考慮了。(不符合團隊的技術棧)

爲什麼要用MongoDB呢?要存儲的數據結構需要支持動態擴展的特性,我就看中MongoDB的靈活性。

當前支付通道是否開啓和關閉?

持久化到MongoDB?不是內存數據庫

上游的業務服務系統。

 

通過 Builder 模式根據請求參數構建對應的組件對象,將組件與外部分離,隱藏組件構建的實現。組件模式+Builder 模式使得支付平臺具備了高擴展性。

 

拆分支付:適用於限額或金額較大場景。

合單支付:適用於保險等分賬到不同收款賬號的場景。

系統功能整體架構。

收銀臺主要由三部分組成:訂單基本信息(含訂單號及支付金額)、訂單詳情(含日期信息、商品信息及基礎信息)、支付方式(平臺支付、信用支付等)。

 

1、一訂單對應多商品,一個主訂單包含多件商品,一訂單 VS 多商品的創單模式基本支持目前所有場景,包括未來可能的購物車模式。

2、一訂單對應多支付。一訂單 VS 多支付單模型更好的支持了馬蜂窩的支付場景。普通訂單用戶選擇支付寶、微信等渠道會生成一個支付單;當金額超過 5000 元時可以選擇拆分訂單金額支付,此時會生成多個支付單;如果下單勾選保險就會走第三方合單支付,會生成兩個支付單;

 

使用模版方法設計模式,在基類中定義了一個標準流程,具體的實現在通道各自的實現類中。客戶類只需要關心基類的公共方法,和具體通道無關。

 

支撐層包含監控報警、日誌管理、加簽驗籤、配置管理、消息總線等模塊。其中日誌使用 ELK 進行收集管理,系統配置採用公司自研的分佈式配置中心進行管理,消息總線也是使用公司二次封裝的 RabbitMQ 進行消息分發及消費。

 

細描述該監控報警系統的功能及設計思路。

爲保證監控的實時性及有效性,監控依賴的資源如數據庫必須和業務庫要進行隔離(避免雞蛋放在同一個籃子裏)。支付監控系統涵蓋了 API 監控、服務性能監控、數據庫監控等,能夠提供統一的報警、分析和故障排除能力。從異常數據採集到故障問題主動發現及穩定性趨勢分析,爲支付體系優化提供數據支撐。

 

數據庫關係模型分析(用戶,商品,訂單項,訂單)一對一,一對多,多對多。

用戶表,商品表,訂單表,訂單項表。

分析他們之間的關係

1一個訂單隻屬於一個用戶;一個用戶可以擁有很多訂單; 一對多

2 一個訂單裏面有多個訂單項,一個訂單項只屬於一個訂單。一對多。

3 一個訂單項只屬於一個商品,一個商品可以有很多個訂單項。(一個訂單項,一種商品。)

 

一個訂單對應多件商品實現

1)order表:表示此次交易的所有商品項,類似於超市小票;

2)orderitem表:表示此次訂單中的每個訂單項,類似於小票中的各個商品項;

一個訂單id對應多個訂單項記錄;

3)訂單主表包括買家信息,訂單總額,是否已支付。(是否可以拆分部分支付,整體支付)

4)是否允許拆單支付?

拆單支付,多件商品拆單支付,單件商品(系列商品)拆單支付。

 

簡單解析一下拆單的流程。一般在下單時會考慮商家分類與倉庫的因素進行拆單,其他的因素會在支付後發貨前再考慮進去,用於拆分發貨單。

前端用戶看到的只是一個訂單號。

 

電商中的“拆單”。拆單,就是客戶在下單之後,爲了發貨和結算方便,需要對訂單進行拆分。上面的例子中,就是一筆359元的交易被拆成了4個訂單。前臺顯示給客戶的是子訂單編號,後續取消支付、物流跟蹤、退換貨、確認收貨等處理也是在子訂單上進行操作。

 

如何拆單?

1,在提交訂單後支付之前拆單,拆分不同的訂單。

這個階段主要是判斷商品是否歸屬不同店鋪,若歸屬不同店鋪,則需要按照店鋪維度進行拆單。例如不同淘寶店的商品同時下單會按照店鋪進行拆單。此時若客戶放棄支付,回到“待付款”頁面,看到的就是多個訂單,再次支付時只能分開支付。

2,在下單之後,發貨之前,按照最後的發貨包裹去拆分發貨單,一筆訂單可能對應多個物流單。

商品所屬不同倉庫,需要拆單。例如購買京東自營的商品,但是在不同庫房存放,就會按照發貨倉庫進行拆單。

某些商品品類由於屬性和價值的不同,需要特殊包裝或單獨包裝,同樣會產生拆單需求。例如易碎品需要單獨包裝。

單個包裹的重量或體積超過物流公司規定要求,需要拆分不同的包裹。

 

訂單已完成,超過退款期限。

退款標識,退款後該筆訂單剩餘用戶支付金額;

RefundMark 退款標識 無退款、存在退款、完全退款

RemainderAmount 退款後該筆訂單剩餘用戶支付金額

PayAmount - RemainderAmount = 退款金額。

 

 

技術博客:

https://blog.csdn.net/dev_csdn/article/details/78949203

https://blog.csdn.net/weixin_43846997/article/details/94689871

訂單關係: 用戶、商品、訂單、訂單項表之間的關係

https://blog.csdn.net/qq_39577901/article/details/90665455

https://blog.csdn.net/qq_39128354/article/details/81428050

https://blog.csdn.net/qq_41937388/article/details/93377863

http://bbs.paidai.com/topic/1477312

https://blog.csdn.net/a610786189/article/details/87874263

 

 

 

發佈了303 篇原創文章 · 獲贊 104 · 訪問量 51萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章