支付子系統架構及常見問題

支付流程

? ? 對于支付系統來說,它最重要的其實是安全,所以整個支付流程采用秘鑰加簽的方式進行操作,一共四對秘鑰,以支付寶在線支付為例子,首先通過RSA2算法生成商戶公鑰以及商戶私鑰,同時支付寶平臺會提供支付寶公鑰和支付寶私鑰,將支付寶公鑰下載到平臺項目中,同時將商戶公鑰上傳到支付寶后臺,當用戶在前端表單中填寫好充值金額后,生成對應商戶訂單,如果用戶選擇支付,將會把支付價格、訂單號以及訂單描述三個參數排列組合后利用商戶私鑰進行加簽操作,同時將密文url進行重定向到支付寶統一支付接口,支付寶平臺會利用商戶公鑰進行驗簽操作,驗簽通過后將對支付寶錢包余額進行減量操作,同時利用支付寶私鑰對回調參數進行加密,包括商戶訂單號,支付寶訂單號以及支付狀態,支付成功后,支付寶平臺會將帶參進行回跳操作,回調到平臺后,利用支付寶公鑰對參數進行解密,隨后利用回調的商戶訂單號或者支付寶訂單號對平臺的錢包余額以及訂單狀態進行修改操作。

支付一致性問題

? ? 由于我們平臺的充值業務會面臨一些高并發情況,也就是單用戶可能同一時間點同時支付充值操作,如果一秒內同時有三筆50元的支付請求成功,后臺可能會出現支付一致性問題,也就是余額可能只增加50的情況,這里為了保持數據一致性,我們采用了redis的setnx分布式鎖進行操作,當單用戶進行余額修改流程之前,先利用商戶uid作為key獲取分布式鎖,余額修改完成后,釋放分布式鎖,一般情況下,考慮到程序的健壯性,防止服務宕機意外報錯等情況發生,會將釋放鎖放到異常捕獲機制的finally中,因為理論上finally肯定會執行,不會出現死鎖問題,您覺得finally會百分之百執行嗎?其實不一定,因為機房可能會發生物理斷電的問題,即使進入try代碼塊,finally也不一定會執行,這樣就造成了死鎖問題,所以需要給分布式鎖設置一個10秒的生命周期,如果10秒內沒有修改成功,我們會認為該操作發生了異常自動釋放鎖。

分布式鎖問題

? 設置了過期時間,如果業務還沒有執行完成,但是redis鎖過期了,怎么辦?

? 加鎖的時間是30秒.如果加鎖的業務沒有執行完,那么到 30-10 = 20秒的時候,就會進行一次續期,把鎖重置成30秒.那業務的機器萬一宕機了呢?宕機了定時任務跑不了,就續不了期,那自然30秒之后鎖就解開了.

具體使用redisson模塊

友商QPS問題

? ? 在做三方支付平臺對接的時候,實際上支付寶的統一支付接口是有qps限制的,qps限制是100,也就是一秒內只支持100單的支付請求,超出的會直接返回403狀態碼,其實這種設計也是合理的,因為友商沒有必要幫我們承擔高并發請求,所以我在訂單支付和請求支付寶接口之間做了一個緩沖區,生產者不會直接和消費者產生關系,而是通過緩沖區解耦,這個緩沖區就是異步任務隊列,隊列容器我采用redis數據庫,因為redis性能優勢比較明顯,同時內置的list數據類型比較契合隊列這種數據結構,工具類內置了,初始化方法,入隊方法,出隊方法,隊列長度,以及查重唯一方法。

? ? 每當商戶提交支付請求,將訂單id進行入隊操作,遵循fifo原則,在消費者端使用多線程的方式進行消費,也就是出隊操作,這里的線程數我們可以通過變量進行控制,峰值線程數大概維持在80左右,不會突破100,起到一個削峰填谷的作用。

支付回跳問題

? ?這是QA提出一個問題,就是在支付過程中,會有因為網絡因素或者其他原因導致支付寶沒有回跳成功,此時客戶端就會停留在支付頁面動不了,造成問題,其實沒有回跳成功,不外乎兩種結果,就是支付成功,或者支付失敗,解決這個問題可以采用定時任務,每隔十秒檢測訂單狀態為支付中的訂單,通過訂單id做為參數,請求支付寶的訂單查詢接口,用來判斷是否支付成功,隨后定時任務會自動將接口返回的訂單狀態同步到數據庫的訂單狀態中,這里定時任務我采用的是redis中的有序集合,利用zadd方法,將支付中狀態訂單id作為key,delay參數設置為當前時間戳加10秒后時間,入庫。將時間作為score標識物,出隊調用zrangebyscore方法,min_score永遠為0,max_score就是當前時間戳,這樣遍歷會形成一個實踐窗口,只要定時任務進入時間窗口,就會自動執行,非常方便。

延時隊列實現

class DelayRedisQueue:def __init__(self,key):self.key = keyself.r = redis.Redis(decode_responses=True)# 入隊def add(self,uid,delay=0):print("延時隊列入隊,%s秒后執行刪除uid%s的任務" %(delay,uid))self.r.zadd(self.key,{uid:time.time()+delay})# 刪除延時任務def remove(self,uid):return self.r.zrem(self.key,uid)# 出隊邏輯def pop(self):# 起始位置min_score = 0# 區間結束為止max_score = time.time()# 獲取隊列res = self.r.zrangebyscore(self.key,min_score,max_score,start=0,num=1,withscores=False)if res == None:print("暫無延時任務")return Falseif len(res) == 1:print("延時任務到期,返回執行任務的uid%s" % res[0])return res[0]else:print("延時任務沒有到時間")return False

訂單緩存問題 mysql-redis數據一致性問題

????????我的訂單模塊由于讀取的是訂單表,為了分擔數據庫壓力,我們使用redis進行緩存操作,但是如果訂單狀態修改了,redis中的數據需要做同步,這就帶來了mysql-redis的數據同步問題。

????????最終一致性強調的是系統中所有的數據副本,在經過一段時間的同步后,最終能夠達到一個一致的狀態。因此,最終一致性的本質是需要系統保證最終數據能夠達到一致,而不需要實時保證系統數據的強一致性。

所以,我們追求的是盡可能保證緩存和數據庫的最終一致性。

??????在開始之前,我們先來科普一下緩存+數據庫讀寫,最經典的Cache Aside Pattern。

? ?????????讀取:先讀取緩存,緩存里沒有,讀取數據庫,然后返回響應,順斌保存緩存

???????????更新:先更新數據庫,然后刪除緩存

為什么是刪除緩存,而不是更新緩存?

????????并發情況下更新緩存可能會帶來種種問題,直接刪除緩存更加穩妥。 緩存更新在很多時候需要耗費資源,直接刪除,用時再從數據庫讀取,寫進緩存,更省性能。

一致性問題

那么我們采用這種先更新數據庫,再刪除緩存,可能會出現什么問題呢?

?假如,我們更新數據庫成功,接下來還沒來刪除緩存,或者刪除緩存失敗怎么辦?

那么很明顯,這時候其它線程進來讀的就是臟數據。

先刪除緩存,再更新數據庫一致性問題

我們看一下,如果先刪除緩存,再更新數據庫可能會帶來什么問題。在并發情況下,先刪除緩存,再更新數據庫,此時數據庫還未更新成功,這時候有其它線程進來了,讀取緩存,緩存不存在,讀取數據庫,讀取的是舊值,這時候,緩存不一致就發生了。

延時雙刪

就是在刪除緩存,更新數據庫之后,休眠一段時間后,再次刪除緩存。利用的也是延時隊列操作

這就是支付系統的介紹。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/96689.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/96689.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/96689.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

內存傳輸速率MT/s

1 0 0 0 0 0 0 0 0 010 9 8 7 6 5 4 3 2 1十 億 千 百 十 萬 千 百 十 個億 萬 萬 萬傳輸速率 …

.env文件的作用和使用方法

目錄 什么是 .env 文件? 為什么要使用 .env 文件?(好處) 如何使用 .env 文件? 通用步驟: 具體技術棧中的實現: 最佳實踐和注意事項 總結 什么是 .env 文件? .env 文件&#x…

深度拆解 Python 裝飾器參數傳遞:從裝飾器生效到參數轉交的每一步

在 Python 裝飾器的學習中,“被裝飾函數的參數如何傳遞到裝飾器內層函數”是一個高頻疑問點。很多開發者能寫出裝飾器的基本結構,卻對參數傳遞的底層邏輯一知半解。本文將以一段具體代碼為例,把參數傳遞過程拆成“裝飾器生效→調用觸發→參數…

【Vue2 ?】Vue2 入門之旅 · 進階篇(七):Vue Router 原理解析

在前幾篇文章中,我們介紹了 Vue 的性能優化機制、組件緩存等內容。本篇將深入解析 Vue Router 的原理,了解 Vue 如何管理路由并進行導航。 目錄 Vue Router 的基本概念路由模式:hash 和 history路由匹配原理導航守衛Vue Router 的路由過渡動…

Linux磁盤級文件/文件系統理解

Linux磁盤級文件/文件系統理解 1. 磁盤的物理結構 磁盤的核心是一個利用磁性介質和機械運動進行數據讀寫的、非易失性的存儲設備。 1.1 盤片 盤片是傳統機械硬盤中最核心的部件,它是數據存儲的物理載體。盤片是一個堅硬的、表面極度光滑的圓形碟片,被安裝…

【星海出品】rabbitMQ - 叁 應用篇

rabbitMQ 的基礎知識這里就不闡述了,可以參看我早年寫的文章 -> rabbitMQ 入門 https://blog.csdn.net/weixin_41997073/article/details/118724779 Celery 官網:http://www.celeryproject.org/ Celery 官方文檔英文版:http://docs.celeryproject.org/en/latest/index.h…

C# 每個chartArea顯示最小值、平均值、最大值

private void AddStatisticsAnnotations(ChartArea chartArea, int channelIndex) {RemoveExistingAnnotations(channelIndex);// 獲取ChartArea的相對坐標(百分比)float chartAreaX chartArea.Position.X; // X坐標(百分比)floa…

打破“不可能三角”:WALL-OSS開源,具身智能迎來“安卓時刻”?

目錄 引言:當“大腦”學會思考,機器人才能走出實驗室 一、具身智能的“不可能三角”:機器人“大腦”的核心困境 二、WALL-OSS的四把重錘:如何系統性地破解難題? 2.1 第一錘:更聰明的“大腦”架構 —— …

SigNoz分布式追蹤新體驗:cpolar實現遠程微服務監控

前言 SigNoz是一款開源的應用性能監控工具,專為微服務架構設計,集成了指標、追蹤和日志分析功能。它能夠全面監控分布式系統的性能,幫助開發團隊快速定位問題根源。SigNoz支持OpenTelemetry協議,可以無縫集成各種編程語言和框架&…

python編程原子化多智能體綜合編程應用(下)

上述代碼實現了基于Mesa框架的診斷智能體類,包含以下核心功能: 模塊化設計:通過類屬性分離數據與行為,支持不同專科智能體的擴展 狀態管理:實現idle/processing/error等狀態轉換,支持任務調度 診斷推理:集成機器學習模型,支持癥狀提取與多分類診斷 錯誤處理:包含模型加…

QT M/V架構開發實戰:QSqlQueryModel/ QSqlTableModel/ QSqlRelationalTableModel介紹

目錄[TOC](目錄)前言一、初步介紹二、QSqlQueryModel1.基礎定位2.特點3.核心接口4.典型用法5.優缺點三、QSqlTableModel1.基礎定位2.特點3.核心接口4.典型用法5.優缺點四、QSqlRelationalTableModel1.基礎定位2.特點3.核心接口4.典型用法 (示例:employees表有 dept_…

Terraform 從入門到實戰:歷史、原理、功能與阿里云/Azure 上手指南

前言:在云時代,企業的IT基礎設施早已從“幾臺服務器”演變為“橫跨多云的復雜網絡、計算、存儲集群”。但隨之而來的,是管理復雜度的爆炸式增長:開發環境和生產環境不一致、手動配置容易出錯、多云平臺操作方式各異、資源變更難以…

【計算機網絡 | 第10篇】信道復用技術

文章目錄信道復用技術:高效利用通信資源的智慧方案一、頻分復用(FDM):按頻率劃分的并行通道二、時分復用(TDM):按時間分割的輪流占用三、統計時分復用(STDM):…

安卓13_ROM修改定制化-----禁用 Android 導航按鍵的幾種操作

Android 設備的導航按鍵通常包括后退鍵(Back)、主頁鍵(Home)和最近鍵(Recents),這些按鍵位于屏幕底部或設備實體區域。禁用導航按鍵可以幫助在特定應用場景(如信息亭模式或兒童鎖模式)中限制用戶操作。安卓設備上禁用底部虛擬導航鍵(返回、主頁、多任務鍵)有多種方法…

通過S參數測量評估電感阻抗:第2部分

S21雙端口分流和雙端口串聯方法 T這是兩篇文章中的第二篇,專門討論使用網絡分析儀測量 S 參數進行電感阻抗評估主題。上一篇文章 [1] 描述了阻抗測量和計算S11使用單端口分流器、雙端口分流器和雙端口串聯方法的參數。本文專門介紹阻抗測量和計算S21使用雙端口分流…

[deepseek] C語言頭文件與匯編實現討論

我想詢問一種代碼實現方式,使用C語言,例如main.c包含了自己編寫的庫文件abc.h,我想問的是:一、abc.h中是否可以有實現函數的代碼;二、abc.h中的函數是否可以在另一個后綴為asm的匯編文件中實現?非常好&…

`.cursorrules` 與 `.cursorcontext`:Cursor AI 編程助手時代下的“雙軌配置”指南

.cursorrules 與 .cursorcontext:AI 編程助手時代下的“雙軌配置”指南關鍵詞:Cursor、AI 編程、上下文管理、開發規范、技術治理 適合讀者:前端 / 全棧工程師、技術負責人、AI 輔助編程實踐者1. 為什么又多了兩個“點”文件? 隨著…

XR 和 AI 在 Siggraph 2025 上主導圖形的未來,獲取gltf/glb格式

Meta 的 Boba 和 Tiramisu XR 耳機(來源:Meta) Siggraph 2025 今年重返不列顛哥倫比亞省溫哥華,慶祝《玩具總動員》誕生 30 周年和視頻游戲實時渲染 20 周年。雖然 Siggraph 需要時間來欣賞過去,但它更多的是展望未來…

在 Ubuntu 22.04 系統(CUDA 12.9)中,通過本地DEB 包安裝 cuDNN 9.13.0 的方法步驟

以下是在 Ubuntu 22.04 系統(CUDA 12.9)中,通過本地單個 DEB 包安裝 cuDNN 9.13.0 的完整步驟,核心包含 GPG 密鑰配置與包安裝驗證,確保每一步可執行。 一、安裝前核心檢查(必做) 確保系統已滿足基礎條件,避免安裝失敗: 驗證 CUDA 版本:打開終端執行命令,確認當前…

Element 中 upload 編輯回顯文件上傳信息技巧

文章目錄需求分析需求 upload 編輯狀態下回顯已上傳的文件信息 分析 添加fileList <el-uploadstyle"width: 100%"ref"uploadRef"class"upload-demo"action"/prod-api/jc/files/upload"multiple:limit"1":on-success&q…