提及支付平臺,支付寶量級的支付平臺和一個小型公司的支付不可同日耳語。一個初創或剛創業一兩年的公司,一沒人力,二沒財力的狀況下,若是也想對接支付那怎麼辦呢?感謝支付寶和微信支付,兩大行業巨頭提供了簡單易用的方案,簡化了對接流程,又能支持大部分銀行。今天咱們就來根據不一樣業務規模,設計一個能經受業務考驗的支付平臺。 html
舉個例子,阿力空閒時間,接了個外包的分銷系統。業務模型如:成爲會員,能夠自動帶二維碼的分銷海報,掃描你二維碼的人成爲會員後,你得到提成。 html5
這個例子有幾個核心步驟: redis
申請會員,支付成爲會員,自動生成海報, docker
計算分銷提成。 數據庫
有點小挑戰的自動生成海報。這個能夠參考微信參數二維碼接口和GDI+繪製圖片來搞定,利用html5的canvas也能搞定。 canvas
最核心的部分,固然是支付。 緩存
先來一張訂單表流程圖壓壓場面。 服務器
訂單模型 微信
前些天看領域驅動提到了核心域和子域,那麼整個交易流程是是這個模型的核心域,訂單表是交易流程的子域。 架構
我大概說下這些字段,業務類型和業務id以及業務處理url實現了各個業務的解藕,各個業務線都有本身的限界上下文。它能夠根據取消日期和取消地址完成訂單的取消動做,能夠根據支付平臺交易id和支付平臺查詢對帳。業務通知狀態是用來綜述通知業務處理是否成功。說完了訂單,讓咱們來看下總體交易流程。
交易流程
訂單有三個主流程,提交訂單是用戶主動觸發,支付回調是屬於支付平臺觸發,定時取消是後臺任務根據設定的取消時間自動運行,小業務能夠不考慮訂單取消問題。
這樣來講,初版支付中心就完成了。因爲剛上線,流量天天不多,平穩了運行一段時間後,也許會出現支付平臺支付,但搭建的支付中心卻未支付,只能手動修改數據庫了,並觸發業務回調了,這在最終一致性裏,能夠成爲人工補償。後來不厭其煩,加了個支付日誌,記錄任何與支付平臺交互的信息,而後每隔一段時間掃描最近變動的日誌表,並和訂單表對比,發現不匹配的,修復爲已支付,完美的解決了這個問題,這在最終一致性裏,可歸納爲定時補償。
交易日誌表
老闆缺乏人手,業務量又上升,又對阿力解決問題的能力很欣賞,就直接把阿力工資翻倍從原公司挖了過來。(故事純屬虛構)
剛過來新公司不久,就接到了一筆融資,而後新公司擴招了不少同事,市場銷售人一多,產品線更多,線上支付流量也加快起來。阿力信心滿滿,以爲頗有幹勁。得意不久,就遇到了服務線反饋的問題:有客戶重複支付,須要退款。因而改訂單,清理數據,財務退款,臨時解決了問題。後來次數多了,手工處理及易出錯,就查詢支付寶和微信的自動退款接口,而後依賴日誌表記錄過支付成功對比斷定重複支付,發起退款,引入了自動退款流程。
交易流程補充自動退款流程
而後又接到了一個線上客戶須要搶購的需求,每個月有一天集中一塊兒搶,相似小米秒殺那樣。而後到了激動的那天,系統撐過了三分鐘,華麗麗的掛了!熬了二十分鐘才恢復正常。
痛定思通,支付中心進入重構優化階段。因爲公司人員擴張,有時間和精力和能力去重購優化更健康的業務架構。
一,引入消息隊列Rabbitmq支撐流量削峯。如支付回調先進消息隊列,由消息隊列去通知業務。大幅度縮短單次請求處理時間,提高併發能力。
二,全面引入Redis緩存,減少數據庫訪問壓力,部分關鍵業務表啓用HttpRuntime緩存,性能指數級提高。
三,引入專業調度工具quartz.net或hangfire。能夠用來處理定時查詢訂單交易問題,及退費問題。
四,購買商業.net監控平臺,如聽雲。檢測程序性能。
阿力跟隨新公司技術體系,也對支付中心實現了升級。
支付平臺回調通知後,先轉發到消息隊列,由消息隊列來通知業務處理,如失敗後延時轉發到消息隊列繼續執行,最高重試5次,而後發短信或郵件通知責任人。
針對以前線上支付平臺和自建平臺不一致問題,利用hangfire調度機制定時天天晚上拉取一週數據和支付平臺覈對。確保了兩個異構系統的一致性。
爲防止支付平臺同時通知,形成兩條支付日誌,先更新訂單成功後,在隊列裏,用redis的incr和decr原子性操做,來確保只能同時操做一個訂單,另外一個通知延遲處理。重複退款時,也要保證同時只能退款一個訂單號。(同一時間能夠操做不一樣的訂單號,但同一個訂單號必須強制避開併發)
數據庫開啓讀寫分離,部署集羣。
通過阿力和同事們兩個月的合力合做與加班加點,新系統終於在那個客戶第三次線上搶購前一段時間上線。通過線上搶購驗證,新的系統輕輕鬆鬆的抗過了搶購,你們一片歡聲笑語。阿力看到十幾分鍾XX百萬的交易額驚呆了!,這真是金牌客戶啊!
到了年末,微信紅包火熱起來,許多客戶申請開通微信紅包,有家客戶粉絲有二十多萬,發的錢也特別多。當時一到點,十萬人齊刷刷搖手機搶紅包。最後,重啓了幾遍應用程序池也不頂用。針對如此的流量,咱們應該怎麼辦呢?每秒萬級的請求暫時就不是小公司處理的來的,何況這流量就過年纔有,像級了春運。人有那麼多,搶到紅包的人是有限的。百分之九十五的人都是無效流量。那就取巧吧,隨機抽取一部分人的數據進入服務器,其餘的人就本地留存吧,經過這種思路減小了一大部分流量。
只考慮第一,第二階段的話,上面關於支付中心的思考架構是徹底能夠知足交易量的。何況又有多少公司能邁向獨角獸之路呢?
念天地之悠悠,獨愴然而淚下!
上面那種方式雖然取巧,針對特定業務,原本就是搶紅包,大部分人都是無效的,能說的過去,假如是主業務流程有萬級每秒甚至百萬千萬級每秒的請求量應該怎麼辦呢?阿力陷入了迷茫。
據說過docker,kuberneters爲表明的容器編排,據說過CI/CD自動部署,據說過微服務的強大,據說過負載均衡,彷彿都是方向。
大海跨不過陸地,颱風卻能輕易穿梭,大化爲小,繁化爲簡,聚簡成面,規模化微服務也許纔是解決巨量請求之道!(故事純屬虛構,不要代號入座)
說完了解決中小型流量的問題,咱們來了解下一致性問題。
一、關係型數據庫事務追求ACID:
A: Atomicity,原子性
C: Consistency,一致性
I: Isolation,隔離性
D: Durability,持久性
二、CAP(帽子理論)
C:Consistency,一致性, 數據一致更新,全部數據變更都是同步的
A:Availability,可用性, 好的響應性能,徹底的可用性指的是在任何故障模型下,服務都會在有限的時間處理響應
P:Partition tolerance,分區容錯性,可靠性
帽子理論證實,任何分佈式系統只可同時知足二點,無法三者兼顧
三、Base模型:
BA:Basically Available,基本可用
S:Soft State,軟狀態,狀態能夠有一段時間不一樣步
E:Eventually Consistent,最終一致,最終數據是一致的就能夠了,而不是時時保持強一致
利用查詢模式,補償模式,異步確保模式,定時校對模式等可實現分佈式系統最終一致性。
最終一致性更詳細用法參考李豔鵬老師關於分佈式一致性的講解。https://www.jianshu.com/p/1156151e20c8?from=singlemessage&isappinstalled=0
阿力解決了支付中心的穩定問題後,就買了許多書,看到了上面關於最終一致性的陳述時,內心想到,這些都是我已經實現了的,原來還有這麼多頭頭道道??
阿力又看到了領域驅動設計等書,感慨:支付領域模型真是學習領域驅動設計的最好實踐。它具備獨立的限界上下文,經過回調url和其餘業務限界上下文溝通。
最後再用交易流程在作個總結吧!
交易流程
關鍵點:
1.回調部分,有消息隊列通知,並支持失敗重試。
2.天天晚上定時拉取支付平臺對象記錄核帳,保證最終一致性。
3.支付平臺回調時,根據支付日誌斷定是否重複支付,重複支付的發起自動退款。
計劃用.netcore按領域驅動的方式,完成以上設計。日期未定。
全文除附錄部分最終一致性外,均爲原創。如文章能給你帶來幫助,請點下推薦,感謝支持。