編輯導讀:“熱點賬戶”來源于銀行領域,指的是銀行或支付賬戶等需要進行代收付等業務的中間内部賬賬戶。本文作者圍繞“熱點賬戶”展開分析,提出一些常見的解決思路和案例,希望對你有幫助。
我們經常聽到一個概念“熱點賬戶”,可能很多人不陌生什麼是熱點賬戶,但是對如何解決熱點賬戶問題并沒有系統性的完整的思路。
事物總是發展的,事物所處的場景也是在不斷變化的,基于有限的經驗去解決無限的可能性是很好的技能。我們試圖從認識熱點賬戶開始,再了解幾個常見的解決思路和案例,打開對熱點賬戶的世界。
一、關于賬戶什麼是賬戶這個話題就不展開讨論了,我們之前也寫過很多跟賬戶相關的内容。
了解賬戶的結構是“入賬請求、賬戶流水、賬戶餘額”;入賬請求産生了賬戶流水,賬戶流水更新賬戶餘額;所以其中我們要關注賬戶流水的創建以及賬戶餘額的更新,這裡賬戶餘額的更新要重點關注,這是後續造成熱點賬戶發生的主要的環節。
賬戶的賬務處理主要分三類:收錢,付錢,賬戶間轉賬;收錢針對一個賬戶的餘額增加,付款是一個賬戶的餘額減少,轉賬是兩個賬戶之間一個增加一個減少。
賬戶處理的存在最大并發量,超過這個并發量賬務處理就會出問題;賬戶賬務處理過程的線程控制,無論是收錢、付錢還是轉賬,為了保證賬務的準确性,每次賬務處理都是一個單獨的事務,就算是多個請求同時發生,對賬戶的操作也是一個一個的來;當一筆入賬請求開始處理時賬戶資源會被加鎖,等該筆請求處理完以後會釋放鎖;這樣的話就意味着每一筆賬務處理都會獲得一個時間占用,這個時間内其他入賬是不能操作的,這樣就出現了資源的瓶頸,也就是賬戶的入賬必然存在一個并發的最大阈值,一旦超過這個阈值,就會出現賬戶的性能問題。
熱點字段和熱點事件;在交易并發過程中,有些字段的使用頻率很高,比如流水号、餘額、發生額等字段,這些使用頻率很高的字段稱為熱點字段;導緻熱點字段的事件稱為熱點事件,比如商家結算日,需要給商家結算付款,這時候造成付款專戶的付款并發,這個就是一個熱點事件。
二、熱點賬戶定義業務發生以後會産生業務事件,比如下單支付,業務事件需要申請入賬;當在短時間内産生了大量的業務事件,或者狹義的看有大量的交易産生時,造成高并發的入賬請求,高并發引起了賬戶系統的性能瓶頸而産生了性能問題,進而造成入賬延遲、失敗、賬務準确性等各種賬務問題;而這個過程中涉及到的賬戶我們就稱為熱點賬戶;所以說熱點賬戶是由于高并發交易時頻繁更新賬戶産生性能問題而造成的,所以這裡一個關鍵的前提是“高并發”,那麼熱點賬戶的标準是什麼呢,在一些文獻裡提到以下标準。
- 賬戶每秒有10次以上更新需求
- 串行化時賬戶處理延遲高于1秒以上
我想熱點賬戶産生的根本機理跟城市交通高峰時段的擁堵地段是一個機理,怎麼解決高峰問題,錯峰出行,限号限流,分流等等;同樣熱點賬戶也是,既然是高并發造成的擁堵,我們就可以以降低賬戶上的并發為目的,也就是降低熱點賬戶的操作并發以降低賬戶熱度;像可以緩存記賬,可以批量彙總記賬,可以将賬戶拆分分攤并發,可以進行記賬排隊等等手段都可以降低對賬戶的高并發操作,從而降低賬戶熱度。
三、熱點賬戶常見發生場景既然産生熱點賬戶的原因是高并發造成的賬戶被頻繁更新,所以我們探索熱點賬戶的發生場景就轉換成了探索交易高并發的場景,這些高并發場景都有可能造成熱點賬戶,比如很容易想到“雙11購物節”“微信發紅包”“某自營電商平台的秒殺搶購”“小米官網新品的預售”等。
這裡的場景有的是因為高并發收款造成的,有些是高并發付款造成的;而且收款和付款的熱點賬戶解決方案往往會存在差異,不同場景的收款和付款解決方案也會有差異;就像淘寶雙11收款,淘寶中間賬戶其實因為不外漏給用戶,後續商家履約周期也長,所以時效性要求并不高,可以考慮批量定時入賬、異步入賬、緩存入賬等,不采用實時入賬;所以我們可以将業務場景分為高頻入賬場景和高頻扣款場景;像淘寶雙11的中間擔保賬戶就是高頻入賬造成的熱點賬戶。
我們來分析一下淘寶雙11産生熱點賬戶的場景。
我們在淘寶購物時都清楚,錢是不會直接給到商家的,而是先收到中間擔保賬戶,等履約完成以後才會由擔保賬戶結算給商家,所以這裡對于擔保賬戶來說有兩個過程,一個是用戶購買商品時的收款,另一個是服務履約以後的結算付款,而其中雙11期間的用戶付款就成了熱點事件,從而中間擔保賬戶的收款造成了擔保賬戶成為熱點賬戶。
上面我們介紹了,淘寶擔保賬戶是内部賬戶,并不外漏給用戶或者商家,這樣的話,隻需要實時告訴用戶和商家已經付款成功即可,至于擔保賬戶的入賬可以慢慢的處理;這裡我們也得到了一個思路,解決熱點賬戶要關注兩個問題。
一個是給用戶的反饋:對交易參與者的反饋策略,參與者需不需要實時知道賬戶的處理情況,是隻需要知道結果即可還是需要實時看到賬戶餘額的變化,顯然對于淘寶中間賬戶來說,賬戶參與者是不需要知道賬戶餘額更新情況的,隻需要知道支付成功的反饋結果即可,而這個結果可以依賴渠道的反饋通知,而内部記賬可以不反饋給用戶,這樣的話擔保賬戶就有了足夠的時間和選擇來規避并發問題。
另一個是賬務要求:賬務更新時效性要求高不高,賬務的準确性要求高不高,這裡中間擔保戶對時效性要求不高,準确性肯定是所有賬戶要求都是很高的。
這樣我們可以使用批量的延遲更新中間擔保賬戶的方式來規避雙11高并發交易的入賬請求,以規避熱點賬戶的發生。
這裡我們要知道個事實,數據庫插入數據的并發支持是非常大的,一般不會造成數據庫性能問題,批量插入即可,隻是更新賬戶餘額需要進行鎖處理,會造成性能問題,所以解決淘寶中間賬戶的關鍵是解決賬戶餘額更新問題。
首先我們先将高并發的交易的入賬請求插入到入賬流水表,這時并不着急去更新中間擔保賬戶餘額,此時這些流水我們标記一個入賬狀态“未入賬”;定時的去掃描這個流水表,将掃描到的數據進行加鎖,确保不會被後續入賬或其他處理影響,然後彙總求和,用這個求和的總值去更新中間擔保賬戶的餘額,然後将這一批“未入賬”流水更新為已入賬,然後釋放鎖,這樣就以很小的并發完成了對中間賬戶的更新。
下面我們介紹幾種常見的解決熱點賬戶的方案,并且針對每個方案我們列舉一個實際的案例為補充;對于熱點賬戶的方案設計過程中,我們需要重點關注幾個問題:
- 收支:賬戶是收入熱點賬戶還是支出熱點賬戶
- 内外:賬戶是用戶熱點賬戶還是内部熱點賬戶
- 時效:賬戶是高時效性實時入賬還是不需要高時效性
- 結果:用戶是否需要實時知道入賬結果還是不需要
- 餘額:用戶是否需要實時知道賬戶餘額更新還是不需要
對于方案的設計和選擇可以先做以上幾個方面的分析,然後選擇合适的解決方案;比如上面淘寶中間擔保賬戶對時效性要求不高,用戶不需要感知餘額的場景我們就可以選擇延遲批量彙總入賬。
對于方案的設計,我們就可以基于以上幾個問題從解決“賬戶的單位并發”為核心突破點,因為并發造成的頻繁更新是熱點賬戶産生的根本原因,所以解決的熱點賬戶并發的問題也就可以解決熱點賬戶的問題。
四、限号限流-直接控制并發第一性原理,不想太多,直接解決産生問題的問題本身;并發不是造成熱點賬戶麼,那麼反向思考,這個并發阈值是多少,在賬戶之前設到屏障控制這個阈值,開閘放水,門就這麼大,隻能進來這麼多水,就像很多城市的限号限流一樣,最終的結果肯定是損害一部分車主的體驗;雖然是立竿見影的效果,但是這也是自損800的方案;這裡我們不妨稱之為“熱點閥”。
所以給賬戶安裝“熱點閥”可以解決熱點賬戶問題;但是問題還是比較明顯的,除非你很強勢,比如交通控制,否則以服務為第一客戶優先的企業這種方式一般不會采用。
五、變多為少-明細彙總記賬數據庫插入數據是可以支持非常高并發,可能達到3.2w/s,所以插入流水不是熱點賬戶瓶頸所在,而是餘額更新;所以我們就将“降低賬戶的單位并發”設計思路縮小到了“降低餘額更新并發”的範圍;對于餘額更新就是基于流水去增加或者減少餘額,了解C語言的應該知道,無非就是下面的這個函數(不一定準确,但是這麼個意思)。
balance=balance 發生額
就像新餘額等于當前餘額加上或減去該流水的發生額,降低餘額的更新頻率我們自然就可以想到,可以降低發生額的更新頻率,也就是你們這個多人來更新我,我實在是忙不過來,都堵在門口,不如你們派一個代表10分鐘進來一次,彙總大家的要求我一次性解決;這樣就是我們說的“彙總明細記賬”的方法,這樣的話這個函數從意義上就變成了。
balance=balance sum(一段時間内全部明細的發生額)
這個方案的适用場景就是不需要實時更新餘額,且主要是增加賬戶餘額的場景如果是扣款類場景,可能彙總入賬會造成賬戶餘額透支,不過如果允許賬戶透支,出款類場景也是可以考慮,隻不過對資金管理的時效就會變差,你無法從賬戶餘額直接看到剩餘可用頭寸。
六、排隊辦理-緩沖記賬現在大家經常做核酸,因為并發較大,檢測人員有限不能實時采集樣本,所以大家需要排一個很長的隊伍;同時因為一個人一個人檢測成本也高,效率也低,所以10個人一組進行混采;混采就像我們上面說的指派代表的彙總記賬一樣;所以說我們可以為賬戶設置一個排隊機制,出現高并發賬戶更新不過來時大家進行排隊辦理。
就算排隊可以解決賬戶的并發問題,但是肯定是有天花闆的,就像10個人采樣,100萬人排隊,那要做到什麼時候,也可能發生抱怨和投訴;所以怎麼辦呢?增加檢測點是一個很好的辦法,1000個人采樣,就可以分攤這麼多的要檢測的排隊的人;這就是我們下面要講的“子賬戶拆分”分攤壓力。
七、臨時存放點-緩存入賬高并發請求可以先進行緩存,然後定時将緩存更新到數據庫;這個看起來跟緩沖記賬異曲同工,但這裡有個區别,緩沖記賬時賬務請求還在排隊入賬,而緩存記賬實際上賬務請求已經實時在緩存中完成了記賬;緩存記賬具備緩沖記賬和彙總明細記賬的雙重優點。
這裡要注意因為緩存需要具備賬戶餘額部分的管理,所以賬戶系統的餘額要賦予緩存模塊,緩存模塊在此餘額基礎上進行出金和入金的記賬操作;定期将緩存同步到賬戶系統完成最終的記賬,記賬完成的緩存部分可以進行清空,然後獲得最新的賬戶餘額,以此循環。
八、增加點位-子賬戶拆分當即要解決高并發的熱點賬戶問題又要保證實時性要求時,上面的會影響賬戶更新時效的方案自然就不是首選了,那麼就需要一個能夠支持實時餘額更新的方案了;既然一個賬戶的更新出現了瓶頸,那是不是可以考慮為他找更多的幫手分攤壓力呢?答案是肯定的;我們可以将賬戶進行按需拆分,拆分成多個子賬戶,将高并發請求分配給各個子賬戶,從而每個子賬戶的并發就降下來了;這裡要明确一個問題,這個子賬戶更多是不能讓用戶感知的,隻是内部的處理方案,對用戶來說還是一個賬戶,所以流水和賬戶餘額反映給用戶的都是一個;這就意味着:
賬戶作為一個整體被用戶感知。
這樣的話勢必要增加很多賬戶設計的複雜程度,比如入賬的時候入哪個子賬戶,是平均入賬還是按序入賬,出賬的時候怎麼出,有個别子賬戶餘額不足但是總賬戶餘額充足時怎麼處理;所以說這裡會有一個複雜的賬務處理模型;不管這個模型怎麼設計,要保證金業務上順利完成賬務記錄要求以及用戶的使用體驗,從而确保業務的正常進行。
我之前設計的賬戶系統,每個商家可能會有七八個子賬戶,出款的時候是按照順序出款,就是先扣完一個賬戶扣下一個賬戶。
想起在某支付機構做了斷直連接入網聯的改造項目,其實網聯的項目方案裡提到了其要作為人行支付系統的前置系統做人行熱點賬戶系統的前置緩沖,我想這個設計方法是不是可以借鑒到工作當中。
九、小弟先上-前置緩沖為解決備付金集中存管所形成的熱點賬戶問題,實現對已映射額度管理,網聯構建了“備付金熱點賬戶前置系統”即“RCMP”,用于支付機構通過網聯平台(EPCC)的業務辦理。
前置系統分為額度管理模塊及賬戶管理模塊,網聯将為各支付機構在前置系統中建立賬戶,用于可用額度的監控、已映射額度的管理。
因為網聯是“實時清算,定時結算”,在一個清算周期内淨額軋差了支付機構的支付指令,最後提交給人行的結算請求筆數一個周期從每個機構的上千萬筆到一筆,這個看起來有點像彙總明細記賬,而這個彙總處理的操作是網聯代人行支付系統完成的。
那這麼看,是不是我們工作當中也需求這樣一個前置系統,來幫助賬戶系統完成壓力的分擔,比如要求業務方建設前置模塊,按照要求進行處理加工後請求入賬;特别是賬戶中台,面對衆多業務線時,是不是可以考慮每個業務線在某些場景下都做賬戶前置,完成初步加工後再請求中台賬戶系統,這樣就可以分擔中台的壓力,又不損害賬戶的中台核心能力,業務線也不用完整建設賬戶系統;這裡的思路就是中台不能一攬子大包,一些能力要分攤給業務線,比如業務線的個性化部分,需要業務線做前置層。
十、打鐵還需自身硬-技術性能升級技術層面就不過多讨論了,作為非專業人士,或者說産品視角提些建議“能多增加幾台服務器麼,可以擴充下硬盤麼,你這個cpu可不可以換成頂尖的……”
事物總是變化的,場景也是不斷地更新,面對新的場景,新的問題,曆史的經驗隻能作為解決新問題的參考;不妨在遇到虛拟問題時多思考一下真實的世界,也許會有意料之外的答案!
#專欄作家#
陳天宇宙,陳天宇宙,人人都是産品經理專欄作家。多平台支付領域專欄作者,十年資深産品;天使投資人;專注為10萬支付産品經理和支付機構以及企業提供深度支付内容和服務!
本文原創發布于人人都是産品經理。未經許可,禁止轉載。
題圖來自Unsplash,基于CC0協議。
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!