支付新手高頻易發(fā)故障及應(yīng)對
在支付行業(yè)的技術(shù)領(lǐng)域,新手開發(fā)者常常會遇到各種技術(shù)挑戰(zhàn)和故障。本文匯總了支付新手高頻易發(fā)的故障,并提供了實用的應(yīng)對策略,供大家參考。
一路走來,我犯過很多錯,也引發(fā)過很多線上故障。在帶團隊后,也不斷看到團隊內(nèi)的新人頻繁出現(xiàn)各種線上故障。這些故障或多或少都對公司的業(yè)務(wù)和新人的心理造成了一定的負(fù)面影響。
這里匯總一些新手高頻易發(fā)的故障,以及應(yīng)對策略,少點故障,安心過年。主要包括:渠道返回碼,亂序,三高(高并發(fā)、高性能、高可用),冪等,多幣種等。
1. 對外部渠道的返回碼理解一知半解
無論是四方還是三方,大部分情況下都是調(diào)用外部渠道或銀行做真實的扣款,而渠道對接是新手觸發(fā)故障的高風(fēng)險區(qū)。
首先就是渠道返回碼的映射。最常見的就是把渠道返回“系統(tǒng)異?!薄ⅰ坝唵尾淮嬖凇?、或調(diào)用超時,推進到失敗。
我現(xiàn)在還記得我接入的第一個外部渠道,吭哧吭哧前后忙活了1個多月,終于上線,開量,穩(wěn)定運行,非常開心。
有天財務(wù)小妹找到我,說我接的那個渠道有筆支付訂單對賬出了長款,我們的訂單是失敗的,但是渠道給的對賬文件是成功的。我不敢大意,趕緊去查日志和數(shù)據(jù)庫的數(shù)據(jù),原來是渠道支付接口超時,查詢接口返回“訂單不存在”,被映射到了“失敗”。
當(dāng)時被老板被狠批一頓:“你怎么犯這種低級錯誤!怎么能把訂單不存在映射成失敗呢?”那時年輕,毫不客氣地回敬道:“這是銀行的問題哪,他都告訴我訂單不存在了,我咋還不能推進到失敗呢?我不推進到失敗我推進到哪里?”
雖然嘴硬,心還是虛的。在網(wǎng)絡(luò)環(huán)境下,數(shù)據(jù)包走不同的路由分發(fā),銀行內(nèi)部多個系統(tǒng)之間有延時,最后導(dǎo)致查詢比支付先到,或者查詢時數(shù)據(jù)還沒有落庫,銀行返回訂單不存在,很正常的。
梳理出大致如下幾條準(zhǔn)則:
- 只有明確成功,才能推進成功。
- 只有明確失敗,才能推進失敗。
- 結(jié)果不明確,默認(rèn)全部是“未知”。
- 支付場景謹(jǐn)慎推進到成功,退款、提現(xiàn)、商家打款等場景謹(jǐn)慎推進到失敗。
- 典型的結(jié)果不明確場景有:訂單不存在,系統(tǒng)異常,內(nèi)部錯誤等。
這部分在“渠道返回碼映射設(shè)計與最佳實踐”的那篇文章里寫得更清楚明確,有興趣的可以歷史發(fā)文里面找一找。
2. 缺少亂序的概念
人的大腦是順序思維,但互聯(lián)網(wǎng)世界是亂序的。
比如以前發(fā)生一個線上問題,財務(wù)小妹說和建行的對賬對出了長款:銀行支付成功,我方不是成功。一查,原來是渠道異步通知接口先返回了“成功”,單據(jù)先被推進到了成功,然后同步接口才返回“系統(tǒng)異常”,單據(jù)又被推進到了支付失敗。
這里有兩個問題:
1)不應(yīng)該把系統(tǒng)異常映射到失敗,這個在上面的返回碼映射已經(jīng)說得非常清楚。
2)成功是終態(tài),不應(yīng)該再變更。
第2個問題的解法非常簡單,只需要設(shè)計好狀態(tài)機就行。比如終態(tài)不可變,只有符合要求的初始狀態(tài)+指定事件,才能推進到指定的狀態(tài)。有興趣的,可去找公號歷史發(fā)文里面的“支付交易訂單狀態(tài)機設(shè)計與最佳實踐”,寫得非常詳細(xì)。
不僅僅是外部渠道對接,現(xiàn)在互聯(lián)網(wǎng)應(yīng)用都是微服務(wù)架構(gòu),微服務(wù)之間除了api接口,還通過消息來傳遞數(shù)據(jù),而大部分消息是不保證順序性的。
我時不時聽見一些新人質(zhì)問消息發(fā)送方:“為什么你的數(shù)據(jù)沒有順序,你需要保證你的數(shù)據(jù)要有順序,不然我處理不了!”。我只能啞然一笑。
群里也有小伙伴說某某消息中間件可以保證有序性??墒俏覀?nèi)绻O(shè)計一個系統(tǒng),不依賴中間件來保證順序性,不是更好么?極端場景下,就算消息中間件能保證順序性,但在分布式場景下,我們也無法保證一筆業(yè)務(wù)只在一臺服務(wù)器上處理。
3. 缺少三高的概念
“高并發(fā)、高可用、高性能”雖然很虛,卻又很實在。不同數(shù)量級的并發(fā),對系統(tǒng)的要求是截然不同的?!皦核礼橊劦淖詈笠桓静荨痹诖笠?guī)模交易場景下,不是一句笑話,而是真實存在的。
以前很長一段時間我分辨不出“高并發(fā)”和“高性能”之間區(qū)別,以為兩者是一回事。事實不是,高并發(fā)是指同時能接多少請求,比如同時處理1百個請求,還是1萬個請求,就是并發(fā)的概念。高性能是指一個請求需要處理多少時間,比如平均每個請求處理時間是500毫秒,性能就遠(yuǎn)好于平均處理時間1000毫秒。
舉幾個例子:
高性能:用戶一般可以使用多個支付方式,比如余額、紅包、滿減、外部銀行等,分別保存在不同的子應(yīng)用中,沒有經(jīng)驗的新人,就按順序去各個應(yīng)用中查數(shù)據(jù)。有經(jīng)驗的老人就知道,使用多線程同時去各子應(yīng)用中查數(shù)據(jù)。這就是提高性能的方式。
高可用:以前分享過一個故障,后臺操作出現(xiàn)慢查詢,在線業(yè)務(wù)去緩存查數(shù)據(jù),擊穿到數(shù)據(jù)庫,數(shù)據(jù)庫宕機,進而導(dǎo)致線上業(yè)務(wù)宕機。最后分析下來,在線業(yè)務(wù)對那個緩存數(shù)據(jù)是弱依賴,沒有也能部分有損地處理業(yè)務(wù)。這就是高可用的部分。有興趣的可以看看公號里的歷史發(fā)文中的一些故障分享。
高并發(fā):高并發(fā)引發(fā)的問題太多了。比如代碼new 一個大對象,小流量沒事,流量一大,就會出現(xiàn)頻繁full gc。比如數(shù)據(jù)庫連接沒有按預(yù)期釋放,小流量也沒事,流量一大,連接不夠用,就會出現(xiàn)頻繁報錯。
這三塊在網(wǎng)上有很多資料,邊看邊學(xué)邊實踐,沒什么好辦法。
4. 缺少冪等概念
在支付系統(tǒng)中,冪等極其重要,一旦出現(xiàn)冪等失敗,經(jīng)常導(dǎo)致資損,不是平臺資損,就是用戶資損。
常見有三種:
對外提供的接口升級,導(dǎo)致冪等失效。現(xiàn)在互聯(lián)網(wǎng)應(yīng)用對外的接口都會聲明冪等字段,最怕就是內(nèi)部做升級,不小心把冪等組合修改掉,比如原來使用訂單號,后面使用訂單號+日期,上游訂單號沒有變,日期變了,本應(yīng)該是一筆訂單,因為冪等失敗,就成了兩筆訂單。
調(diào)用下游接口,把下游依賴的冪等字段內(nèi)容修改了。比如下游依賴訂單號+創(chuàng)建日期做冪等,上游在架構(gòu)升級中,傳入了訂單號+當(dāng)前日期,在跨零點的交易中,就可能出現(xiàn)冪等失敗。
使用redis實現(xiàn)的分布式鎖做冪等。redis的可靠性和持久存儲是比不上關(guān)系數(shù)據(jù)庫的,最起碼需要使用關(guān)系數(shù)據(jù)庫的唯一索引做冪等。
冪等在網(wǎng)上有很多資料,值得好好看看。更高階的,還需要考慮異地多活的冪等場景,A機房掛了,去到B機房,會不會冪等失敗。
5. 缺少多幣種或金額單位換算概念
在跨境交易中,必然是多幣種的,不同的幣種,最小單位是不一樣的。人民幣、美元都很標(biāo)準(zhǔn),有元有分,但是日元最小單位就是元,印尼盾雖然最小單位是分,但是日常只會用到元。
在微服務(wù)框架中,如果一些子應(yīng)用中使用分,一些子應(yīng)用使用元,會出現(xiàn)什么情況?
新人還容易犯的一個錯誤就是手動加減乘除,容易出現(xiàn)金額放大縮小100倍,或者出現(xiàn)舍入不正確(舍入有:向下取整,向上取整,四舍五入、銀行家算法等)。尤其是渠道對接時,以為內(nèi)部使用的分,外部渠道接口要求是元,直接乘100,但實際上內(nèi)部應(yīng)用使用的是元,妥妥資損100倍。
解決方案在公號以前的發(fā)文“支付系統(tǒng)金額處理規(guī)范及最佳實踐”中有詳細(xì)說明,有興趣可以去翻翻。
6. 結(jié)束語
上面只是舉了一些常見的例子,無法覆蓋全部。
基本所有的新人都是踩著線上故障在成長。我們能做的,只是提供一些規(guī)范或案例,讓新人能踩在前人的故障上成長,而不全是踩著自己的線上故障在成長。很多時候一不小心因為一個大故障而被清理門戶,成長雖有,代價卻過大,得不償失。
本文由人人都是產(chǎn)品經(jīng)理作者【隱墨星辰】,微信公眾號:【隱墨星辰】,原創(chuàng)/授權(quán) 發(fā)布于人人都是產(chǎn)品經(jīng)理,未經(jīng)許可,禁止轉(zhuǎn)載。
題圖來自Unsplash,基于 CC0 協(xié)議。
- 目前還沒評論,等你發(fā)揮!