.Net架构篇:实用中小型公司支付中心设计
前言
說起支付平臺(tái),支付寶量級(jí)的支付平臺(tái)和一個(gè)小型公司的支付不可同日耳語。一個(gè)初創(chuàng)或剛創(chuàng)業(yè)一兩年的公司,一沒人力,二沒財(cái)力的情況下,如果也想對(duì)接支付那怎么辦呢?感謝支付寶和微信支付,兩大行業(yè)巨頭提供了簡(jiǎn)單易用的方案,簡(jiǎn)化了對(duì)接流程,又能支持大部分銀行。今天我們就來根據(jù)不同業(yè)務(wù)規(guī)模,設(shè)計(jì)一個(gè)能經(jīng)受業(yè)務(wù)考驗(yàn)的支付平臺(tái)。
第一階段
舉個(gè)例子,阿力空閑時(shí)間,接了個(gè)外包的分銷系統(tǒng)。業(yè)務(wù)模型如:成為會(huì)員,可以自動(dòng)帶二維碼的分銷海報(bào),掃描你二維碼的人成為會(huì)員后,你獲得提成。
這個(gè)例子有幾個(gè)核心步驟:
申請(qǐng)會(huì)員,支付成為會(huì)員,自動(dòng)生成海報(bào),
計(jì)算分銷提成。
有點(diǎn)小挑戰(zhàn)的自動(dòng)生成海報(bào)。這個(gè)可以參考微信參數(shù)二維碼接口和GDI+繪制圖片來搞定,利用html5的canvas也能搞定。
最核心的部分,當(dāng)然是支付。
先來一張訂單表流程圖壓壓場(chǎng)面。
訂單模型
前些天看領(lǐng)域驅(qū)動(dòng)提到了核心域和子域,那么整個(gè)交易流程是是這個(gè)模型的核心域,訂單表是交易流程的子域。
我大概說下這些字段,業(yè)務(wù)類型和業(yè)務(wù)id以及業(yè)務(wù)處理url實(shí)現(xiàn)了各個(gè)業(yè)務(wù)的解藕,各個(gè)業(yè)務(wù)線都有自己的限界上下文。它可以根據(jù)取消日期和取消地址完成訂單的取消動(dòng)作,可以根據(jù)支付平臺(tái)交易id和支付平臺(tái)查詢對(duì)賬。業(yè)務(wù)通知狀態(tài)是用來綜述通知業(yè)務(wù)處理是否成功。說完了訂單,讓我們來看下整體交易流程。
交易流程
訂單有三個(gè)主流程,提交訂單是用戶主動(dòng)觸發(fā),支付回調(diào)是屬于支付平臺(tái)觸發(fā),定時(shí)取消是后臺(tái)任務(wù)根據(jù)設(shè)定的取消時(shí)間自動(dòng)運(yùn)行,小業(yè)務(wù)可以不考慮訂單取消問題。
這樣來說,第一版支付中心就完成了。由于剛上線,流量每天很少,平穩(wěn)了運(yùn)行一段時(shí)間后,也許會(huì)出現(xiàn)支付平臺(tái)支付,但搭建的支付中心卻未支付,只能手動(dòng)修改數(shù)據(jù)庫了,并觸發(fā)業(yè)務(wù)回調(diào)了,這在最終一致性里,可以成為人工補(bǔ)償。后來不厭其煩,加了個(gè)支付日志,記錄任何與支付平臺(tái)交互的信息,然后每隔一段時(shí)間掃描最近變更的日志表,并和訂單表對(duì)比,發(fā)現(xiàn)不匹配的,修復(fù)為已支付,完美的解決了這個(gè)問題,這在最終一致性里,可概括為定時(shí)補(bǔ)償。
交易日志表
老板缺少人手,業(yè)務(wù)量又上升,又對(duì)阿力解決問題的能力很欣賞,就直接把阿力工資翻倍從原公司挖了過來。(故事純屬虛構(gòu))
第二階段
剛過來新公司不久,就接到了一筆融資,然后新公司擴(kuò)招了很多同事,市場(chǎng)銷售人一多,產(chǎn)品線更多,線上支付流量也加快起來。阿力信心滿滿,覺得很有干勁。得意不久,就遇到了服務(wù)線反饋的問題:有客戶重復(fù)支付,需要退款。于是改訂單,清理數(shù)據(jù),財(cái)務(wù)退款,臨時(shí)解決了問題。后來次數(shù)多了,手工處理及易出錯(cuò),就查詢支付寶和微信的自動(dòng)退款接口,然后依賴日志表記錄過支付成功對(duì)比判定重復(fù)支付,發(fā)起退款,引入了自動(dòng)退款流程。
交易流程補(bǔ)充自動(dòng)退款流程
然后又接到了一個(gè)線上客戶需要搶購的需求,每月有一天集中一起搶,類似小米秒殺那樣。然后到了激動(dòng)的那天,系統(tǒng)撐過了三分鐘,華麗麗的掛了!熬了二十分鐘才恢復(fù)正常。
痛定思通,支付中心進(jìn)入重構(gòu)優(yōu)化階段。由于公司人員擴(kuò)張,有時(shí)間和精力和能力去重購優(yōu)化更健康的業(yè)務(wù)架構(gòu)。
一,引入消息隊(duì)列Rabbitmq支撐流量削峰。如支付回調(diào)先進(jìn)消息隊(duì)列,由消息隊(duì)列去通知業(yè)務(wù)。大幅度縮短單次請(qǐng)求處理時(shí)間,提升兵法能力。
二,全面引入Redis緩存,減小數(shù)據(jù)庫訪問壓力,部分關(guān)鍵業(yè)務(wù)表啟用HttpRuntime緩存,性能指數(shù)級(jí)提升。
三,引入專業(yè)調(diào)度工具quartz.net或hangfire。可以用來處理定時(shí)查詢訂單交易問題,及退費(fèi)問題。
四,購買商業(yè).net監(jiān)控平臺(tái),如聽云。檢測(cè)程序性能。
阿力跟隨新公司技術(shù)體系,也對(duì)支付中心實(shí)現(xiàn)了升級(jí)。
支付平臺(tái)回調(diào)通知后,先轉(zhuǎn)發(fā)到消息隊(duì)列,由消息隊(duì)列來通知業(yè)務(wù)處理,如失敗后延時(shí)轉(zhuǎn)發(fā)到消息隊(duì)列繼續(xù)執(zhí)行,最高重試5次,然后發(fā)短信或郵件通知責(zé)任人。
針對(duì)之前線上支付平臺(tái)和自建平臺(tái)不一致問題,利用hangfire調(diào)度機(jī)制定時(shí)每天晚上拉取一周數(shù)據(jù)和支付平臺(tái)核對(duì)。確保了兩個(gè)異構(gòu)系統(tǒng)的一致性。
為防止支付平臺(tái)同時(shí)通知,造成兩條支付日志,先更新訂單成功后,在隊(duì)列里,用redis的incr和decr原子性操作,來確保只能同時(shí)操作一個(gè)訂單,另一個(gè)通知延遲處理。
數(shù)據(jù)庫開啟讀寫分離,部署集群。
經(jīng)過阿力和同事們兩個(gè)月的協(xié)力合作與加班加點(diǎn),新系統(tǒng)終于在那個(gè)客戶第三次線上搶購前一段時(shí)間上線。經(jīng)過線上搶購驗(yàn)證,新的系統(tǒng)輕輕松松的抗過了搶購,大家一片歡聲笑語。阿力看到十幾分鐘XX百萬的交易額驚呆了!,這真是金牌客戶啊!
到了年底,微信紅包火熱起來,許多客戶申請(qǐng)開通微信紅包,有家客戶粉絲有二十多萬,發(fā)的錢也特別多。當(dāng)時(shí)一到點(diǎn),十萬人齊刷刷搖手機(jī)搶紅包。最后,重啟了幾遍應(yīng)用程序池也不頂用。針對(duì)如此的流量,我們應(yīng)該怎么辦呢?每秒萬級(jí)的請(qǐng)求暫時(shí)就不是小公司處理的來的,況且這流量就過年才有,像級(jí)了春運(yùn)。人有那么多,搶到紅包的人是有限的。百分之九十五的人都是無效流量。那就取巧吧,隨機(jī)抽取一部分人的數(shù)據(jù)進(jìn)入服務(wù)器,其他的人就本地留存吧,通過這種思路減少了一大部分流量。
只考慮第一,第二階段的話,上面關(guān)于支付中心的思考架構(gòu)是完全可以滿足交易量的。況且又有多少公司能邁向獨(dú)角獸之路呢?
念天地之悠悠,獨(dú)愴然而淚下!
第三階段
上面那種方式雖然取巧,針對(duì)特定業(yè)務(wù),本來就是搶紅包,大部分人都是無效的,能說的過去,假如是主業(yè)務(wù)流程有萬級(jí)每秒甚至百萬千萬級(jí)每秒的請(qǐng)求量應(yīng)該怎么辦呢?阿力陷入了迷茫。
聽說過docker,kuberneters為代表的容器編排,聽說過CI/CD自動(dòng)部署,聽說過微服務(wù)的強(qiáng)大,聽說過負(fù)載均衡,仿佛都是方向。
大海跨不過陸地,臺(tái)風(fēng)卻能輕易穿梭,大化為小,繁化為簡(jiǎn),聚簡(jiǎn)成面,規(guī)模化微服務(wù)也許才是解決巨量請(qǐng)求之道!(故事純屬虛構(gòu),不要代號(hào)入座)
附錄:最終一致性
說完了解決中小型流量的問題,我們來了解下一致性問題。
1、關(guān)系型數(shù)據(jù)庫事務(wù)追求ACID:
A: Atomicity,原子性
C: Consistency,一致性
I: Isolation,隔離性
D: Durability,持久性
2、CAP(帽子理論)
C:Consistency,一致性, 數(shù)據(jù)一致更新,所有數(shù)據(jù)變動(dòng)都是同步的
A:Availability,可用性, 好的響應(yīng)性能,完全的可用性指的是在任何故障模型下,服務(wù)都會(huì)在有限的時(shí)間處理響應(yīng)
P:Partition tolerance,分區(qū)容錯(cuò)性,可靠性
帽子理論證明,任何分布式系統(tǒng)只可同時(shí)滿足二點(diǎn),沒法三者兼顧
3、Base模型:
BA:Basically Available,基本可用
S:Soft State,軟狀態(tài),狀態(tài)可以有一段時(shí)間不同步
E:Eventually Consistent,最終一致,最終數(shù)據(jù)是一致的就可以了,而不是時(shí)時(shí)保持強(qiáng)一致
利用查詢模式,補(bǔ)償模式,異步確保模式,定時(shí)校對(duì)模式等可實(shí)現(xiàn)分布式系統(tǒng)最終一致性。
最終一致性更詳細(xì)用法參考李艷鵬老師關(guān)于分布式一致性的講解。https://www.jianshu.com/p/1156151e20c8?from=singlemessage&isappinstalled=0
后言
阿力解決了支付中心的穩(wěn)定問題后,就買了許多書,看到了上面關(guān)于最終一致性的陳述時(shí),心里想到,這些都是我已經(jīng)實(shí)現(xiàn)了的,原來還有這么多頭頭道道??
阿力又看到了領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)等書,感慨:支付領(lǐng)域模型真是學(xué)習(xí)領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的最好實(shí)踐。它具有獨(dú)立的限界上下文,通過回調(diào)url和其他業(yè)務(wù)限界上下文溝通。
最后再用交易流程在做個(gè)總結(jié)吧!
交易流程
關(guān)鍵點(diǎn):
1.回調(diào)部分,有消息隊(duì)列通知,并支持失敗重試。
2.每天晚上定時(shí)拉取支付平臺(tái)對(duì)象記錄核賬,保證最終一致性。
3.支付平臺(tái)回調(diào)時(shí),根據(jù)支付日志判定是否重復(fù)支付,重復(fù)支付的發(fā)起自動(dòng)退款。
源碼
計(jì)劃用.netcore按領(lǐng)域驅(qū)動(dòng)的方式,完成以上設(shè)計(jì)。日期未定。
聲明
全文除附錄部分最終一致性外,均為原創(chuàng)。如文章能給你帶來幫助,請(qǐng)點(diǎn)下推薦,感謝支持。
相關(guān)文章:
ICanPay 統(tǒng)一支付網(wǎng)關(guān)
ASP.NET Core 2.0 使用支付寶PC網(wǎng)站支付
ASP.NET Core Web 支付功能接入 微信-掃碼支付篇
微信和支付寶支付模式詳解及實(shí)現(xiàn)(.Net標(biāo)準(zhǔn)庫)
原文鏈接:https://www.cnblogs.com/fancunwei/p/9612567.html
.NET社區(qū)新聞,深度好文,歡迎訪問公眾號(hào)文章匯總 http://www.csharpkit.com 
總結(jié)
以上是生活随笔為你收集整理的.Net架构篇:实用中小型公司支付中心设计的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: .Net Core应用框架Util介绍(
 - 下一篇: netcore编程之后面对不习惯的xsh