避免重復(fù)扣款:分布式支付系統(tǒng)的冪等性原理與實踐

1 評論 1928 瀏覽 3 收藏 11 分鐘
B端产品经理要负责对目标行业和市场进行深入的分析和调研,了解客户的需求、痛点、期望和行为,找到产品的价值主张 🔗

在分布式支付系統(tǒng)中,冪等性是確保交易準(zhǔn)確性和用戶信任的核心原則之一。本文從支付架構(gòu)設(shè)計的角度,深入探討了冪等性原理及其在支付系統(tǒng)中的重要性,分析了業(yè)務(wù)冪等、通用冪等組件、全局冪等等多種實現(xiàn)方案及其適用場景,并討論了分布式場景下實現(xiàn)冪等性的挑戰(zhàn)與應(yīng)對策略,供大家參考。

今天聊一個專業(yè)的技術(shù)問題:如何做到分布式場景下的冪等?本文主要講清楚什么是冪等性原理,在支付系統(tǒng)中的重要應(yīng)用,業(yè)務(wù)冪等、全部冪等這些不同的冪等方案選型帶來的收益和復(fù)雜度權(quán)衡,冪等擊穿場景及可能的嚴(yán)重后果。

這也是支付公司面試的必考題目之一。

一、什么是冪等性原理

冪等性是一個數(shù)學(xué)和計算機科學(xué)術(shù)語,用于描述無論操作執(zhí)行多少次,都產(chǎn)生相同結(jié)果的屬性。在軟件行業(yè),應(yīng)用極其廣泛,當(dāng)我們說一個接口支持冪等時,無論調(diào)用多少次,對系統(tǒng)造成的結(jié)果是一致的。

注意這里說的“對系統(tǒng)造成的結(jié)果是一致的”是指系統(tǒng)內(nèi)部數(shù)據(jù)或狀態(tài)的變更,不是指返回值。不同的系統(tǒng)設(shè)計,返回值可能是不一樣的。

舉個例子,你在淘寶免密支付10元,淘寶針對這筆訂單調(diào)用支付寶支付接口進(jìn)行支付,無論是調(diào)用1次,還是調(diào)用100次,最終只扣了你10元。但是第二次有可能返回“重復(fù)請求”,也有可能返回“支付成功”,這個取決于接口設(shè)計。也就是支付寶內(nèi)部只扣了你10元,但是接口可能返回給商戶是是不同的結(jié)果。

我個人傾向于方案一,如果等冪等,就返回:重復(fù)請求。減少誤解,雖然兩種方案中系統(tǒng)都只扣了一次錢。

二、為什么冪等性在支付系統(tǒng)中極其重要

支付系統(tǒng)必須以最高的可靠性和準(zhǔn)確性處理交易,這對于用戶信任至關(guān)重要。如果一個支付系統(tǒng)不能保證冪等性,可能會導(dǎo)致多次扣除同一筆費用,引發(fā)用戶不滿和法律責(zé)任,嚴(yán)重時就會有輿情風(fēng)險,甚至?xí)坏蹁N牌照。

一般情況下,支付系統(tǒng)的冪等性能力要求比電商系統(tǒng)要求更高,如果用戶在電商下單多了,只要沒有支付,用戶還是可以忍受的,但一旦多扣了用戶的錢,后果就會比較嚴(yán)重。

這也是為什么冪等性會是支付系統(tǒng)招人的面試必考題目之一。

三、支付系統(tǒng)中應(yīng)用冪等性的場景

冪等是針對重復(fù)請求的,支付系統(tǒng)一般會面臨以下幾個重復(fù)請求的場景:

用戶多次點擊支付按鈕:在網(wǎng)絡(luò)較差或系統(tǒng)過載情況下,用戶由于不確定交易是否完成而重復(fù)點擊。

自動重試機制:系統(tǒng)在超時或失敗時重試請求,可能導(dǎo)致同一支付多次嘗試。

網(wǎng)絡(luò)數(shù)據(jù)包重復(fù):數(shù)據(jù)包在網(wǎng)絡(luò)傳輸過程中,復(fù)制出了多份,導(dǎo)致支付平臺收到多次一模一樣的請求。

異常恢復(fù):在系統(tǒng)升級或崩潰后,未決事務(wù)需要根據(jù)已有記錄恢復(fù)和完成。內(nèi)部系統(tǒng)重發(fā)操作。

四、冪等解決方案

4.1. 業(yè)務(wù)冪等

所謂業(yè)務(wù)冪等,就是由各域自己把唯一性的交易ID作為數(shù)據(jù)庫唯一索引,這樣可以保證不會重復(fù)處理。

在數(shù)據(jù)庫前面可以加一層緩存來提高性能,但是緩存只用于查詢,查到數(shù)據(jù)認(rèn)為就返回冪等成功,但是但不到,需要嘗試插入數(shù)據(jù)庫,插入成功后再刷新數(shù)據(jù)到緩存。

為什么要使用數(shù)據(jù)庫的唯一索引做為兜底,是因為緩存是可能失效的。

在面臨時經(jīng)常有同學(xué)只回答到“使用redis分布式鎖來實現(xiàn)冪等”,這是不對的。因為緩存有可能失效,分布式鎖只是用于防并發(fā)操作的一種手段,無法根本性解決冪等問題,冪等一定是依賴數(shù)據(jù)庫的唯一索引解決。

大部分簡單的支付系統(tǒng)只要有業(yè)務(wù)冪等基本也夠用了。

4.2. 通用冪等組件

每個域都要做冪等處理,那就單獨出一個獨立的冪等組件,各子業(yè)務(wù)系統(tǒng)通過引用這個公共JAR包解決。

適用場景:應(yīng)用部署不太多的時候。如果應(yīng)用非常多,獨立冪等DB的連接池就不夠用。

這個時候,可以把冪等組件的代碼共用,但是冪等數(shù)據(jù)庫表使用業(yè)務(wù)系統(tǒng)的DB資源。解決獨立冪等DB導(dǎo)致的連接數(shù)不夠用的場景。

4.3. 通用冪等服務(wù)

解決DB連接數(shù)不夠用的第二個解決方案:冪等組件服務(wù)化。這樣的壞處就是復(fù)雜度和耗時RT都會增加,而且冪等服務(wù)有可能成為瓶頸,所以一般很少這么用。

4.4. 全局冪等

在多機房部署情況下,需要解決機房之間的冪等服務(wù)。這就使用到了全局冪等概念。

所謂全局冪等,就是多個機房共用一份冪等數(shù)據(jù),這里面涉及的技術(shù)比較復(fù)雜。除了極少數(shù)全球部署的多活支付系統(tǒng)都用不上。

4.5. 通用冪等數(shù)據(jù)庫表設(shè)計

核心字段:

  • uniqueKey:冪等主鍵,由各應(yīng)用自定義,需要保證全局唯一性,使用這個uniqueKey做hash后分庫分表。比如商戶的收單ID,上游的ID等。
  • appName: 應(yīng)用名稱,比如收單,支付等。
  • siteId:站點ID
  • extInfoMap:擴(kuò)展字段,由各應(yīng)用自定義,比如保存我方單號。

4.6. 方案選型建議

簡單的支付系統(tǒng),只需要使用業(yè)務(wù)冪等就夠。

中型的支付系統(tǒng),推薦使用通用冪等組件。這樣方便運維。

全局冪等方案只有極少數(shù)公司會考慮。

五、分布式場景下實現(xiàn)冪等性的挑戰(zhàn)及應(yīng)對

分布式支付系統(tǒng)面臨的冪等性挑戰(zhàn)核心有兩點:

  1. 如何保證分布于不同地理位置數(shù)據(jù)中心的系統(tǒng)數(shù)據(jù)的一致性。
  2. 冪等數(shù)據(jù)和業(yè)務(wù)數(shù)據(jù)跨庫事務(wù)一致性。比如冪等已經(jīng)入庫成功,但是業(yè)務(wù)數(shù)據(jù)庫入庫失敗。

為了解決這些挑戰(zhàn),可以采取以下解決方案:

  • 使用全局唯一的交易ID,跟蹤每次支付請求,防止重復(fù)處理。
  • 冪等住了之后,還需要繼續(xù)查詢業(yè)務(wù)數(shù)據(jù),如果查詢失敗,仍然執(zhí)行業(yè)務(wù)操作。
  • 構(gòu)建強大的狀態(tài)機推進(jìn)能力,嚴(yán)格定義事務(wù)各個狀態(tài)的轉(zhuǎn)換。
  • 冪等服務(wù)的高可靠性。

六、冪等被擊穿場景及可能的嚴(yán)重后果

盡管有了上述措施,冪等性仍然可能因為以下原因失效:

  • 在分布式系統(tǒng)中,由于同步延遲,導(dǎo)致多個節(jié)點未能即時識別重復(fù)請求。
  • 請求流量切換。原本應(yīng)該路由A機房的數(shù)據(jù)路由到了B機房,但是B機房的冪等數(shù)據(jù)缺失。
  • 生成全局唯一ID的算法出現(xiàn)故障或人為變更,同一筆業(yè)務(wù)可能出現(xiàn)了2個業(yè)務(wù)ID。

在支付系統(tǒng)中,只要冪等被擊穿,基本上都會出現(xiàn)資損事件。有時候是用戶資損,有時候是平臺資損。曾經(jīng)碰到一個真實案例,上游域把某個冪等字段組成規(guī)則的取值變了,但是下游不知道,導(dǎo)致下游冪等失敗,對同一筆業(yè)務(wù)處理了2次,資損出現(xiàn)。

七、結(jié)束語

冪等性是分布式支付系統(tǒng)的基本要求,對于確保交易的正確性和避免重復(fù)扣費至關(guān)重要。除了支付系統(tǒng)外,各種交易類的互聯(lián)網(wǎng)應(yīng)用比如電商等基本上都需要有冪等能力。

本文由人人都是產(chǎn)品經(jīng)理作者【隱墨星辰】,微信公眾號:【隱墨星辰】,原創(chuàng)/授權(quán) 發(fā)布于人人都是產(chǎn)品經(jīng)理,未經(jīng)許可,禁止轉(zhuǎn)載。

題圖來自Unsplash,基于 CC0 協(xié)議。

更多精彩內(nèi)容,請關(guān)注人人都是產(chǎn)品經(jīng)理微信公眾號或下載App
"="" class="meta">08-216329 瀏覽
"="" class="meta">
"="" class="meta"> "="" src="https://image.woshipm.com/2023/04/20/23ff8056-df4b-11ed-9648-00163e0b5ff3.jpg!/both/120x80" alt="小紅書七夕上線新的社交功能「共享收藏夾」|談?wù)勎业乃伎?>
="" data-id="12">
"="" src="https://image.woshipm.com/2023/04/20/23ff8056-df4b-11ed-9648-00163e0b5ff3.jpg!/both/120x80" alt="小紅書七夕上線新的社交功能「共享收藏夾」|談?wù)勎业乃伎?>
="" data-id="12">
"="" src="https://image.woshipm.com/2023/04/20/23ff8056-df4b-11ed-9648-00163e0b5ff3.jpg!/both/120x80" alt="小紅書七夕上線新的社交功能「共享收藏夾」|談?wù)勎业乃伎?>
="" data-id="12">
"="" src="https://image.woshipm.com/2023/04/20/23ff8056-df4b-11ed-9648-00163e0b5ff3.jpg!/both/120x80" alt="小紅書七夕上線新的社交功能「共享收藏夾」|談?wù)勎业乃伎?>
="" data-id="12">
"="" src="https://image.woshipm.com/2023/04/20/23ff8056-df4b-11ed-9648-00163e0b5ff3.jpg!/both/120x80" alt="小紅書七夕上線新的社交功能「共享收藏夾」|談?wù)勎业乃伎?>
="" data-id="12">“做活動嘛,不就是關(guān)關(guān)難過關(guān)關(guān)過”
02-286094 瀏覽
“做活動嘛,不就是關(guān)關(guān)難過關(guān)關(guān)過”