微信紅包實現(xiàn)原理
信紅包實現(xiàn)原理
以下內(nèi)容來源于QCon某高可用架構(gòu)群聊天記錄整理 背景:有某個朋友咨詢微信紅包的架構(gòu),在官方或非官方同學(xué)的解釋和討論中得出以下討論內(nèi)容,在此期間有多個同學(xué)發(fā)紅包做現(xiàn)網(wǎng)算法測試。
搶紅***程
當(dāng)有人在群里發(fā)了一個N人的紅包,總金額M元,后臺大概發(fā)生的事情如下:
一、發(fā)紅包后臺操作:
-
在數(shù)據(jù)庫中增加一條紅包記錄,存儲到CKV,設(shè)置過期時間;
-
在Cache(可能是騰訊內(nèi)部kv數(shù)據(jù)庫,基于內(nèi)存,有落地,有內(nèi)核態(tài)網(wǎng)絡(luò)處理模塊,以內(nèi)核模塊形式提供服務(wù)))中增加一條記錄,存儲搶紅包的人數(shù)N
二、搶紅包后臺操作:
-
搶紅包分為搶和拆,搶操作在Cache層完成,通過原子減操作進(jìn)行紅包數(shù)遞減,到0 就說明搶光了,最終實際進(jìn)入后臺拆操作的量不大,通過操作的分離將無效請求直接擋在Cache層外面。這里的原子減操作并不是真正意義上的原子減操作,是 其Cache層提供的CAS,通過比較版本號不斷嘗試,存在一定程度上的沖突,沖突的用戶會放行,讓其進(jìn)入下一步拆的操作,這也解釋了為啥有用戶搶到了拆 開發(fā)現(xiàn)領(lǐng)完了的情況。
-
拆紅包在數(shù)據(jù)庫完成,通過數(shù)據(jù)庫的事務(wù)操作累加已經(jīng)領(lǐng)取的個數(shù)和金額,插入一條領(lǐng)取 流水,入賬為異步操作,這也解釋了為啥在春節(jié)期間紅包領(lǐng)取后在余額中看不到。拆的時候會實時計算金額,其金額為1分到剩余平均值2倍之間隨機(jī)數(shù),一個總金 額為M元的紅包,***的紅包為 M * 2 /N(且不會超過M),當(dāng)拆了紅包后會更新剩余金額和個數(shù)。財付通按20萬筆每秒入賬準(zhǔn)備,實際只到8萬每秒。
FAQ
-
既然在搶的時候有原子減了就不應(yīng)該出現(xiàn)搶到了拆開沒有的情況?
這里的原子減并不是真正意義上的原子操作,是Cache層提供的CAS,通過比較版本號不斷嘗試。 -
cache和db掛了怎么辦?
主備 +對賬 -
有沒有紅包個數(shù)沒了,但余額還有情況?
沒有,程序***會有一個take all操作以及一個異步對賬保障。 -
為什么要分離搶和拆?
總思路是設(shè)置多層過濾網(wǎng),層層篩選,層層減少流量和壓力。這個設(shè)計最初是因為搶操作是業(yè)務(wù)層,拆是入賬操作,一個操作太重了,而且中斷率高。 從接口層面看,***個接口純緩存操作,搞壓能力強,一個簡單查詢Cache擋住了絕大部分用戶,做了***道篩選,所以大部分人會看到已經(jīng)搶完了的提示。 -
搶到紅包后再發(fā)紅包或者提現(xiàn),這里有什么策略嗎?
大額優(yōu)先入賬策略 -
有沒有從數(shù)據(jù)上證明每個紅包的概率是不是均等?
不是絕對均等,就是一個簡單的拍腦袋算法。 -
拍腦袋算法,會不會出現(xiàn)兩個***?
會出現(xiàn)金額一樣的,但是手氣***只有一個,先搶到的那個***。 -
發(fā)紅包人的錢會不會凍結(jié)?
是直接實時扣掉,不是凍結(jié)。 -
采用實時算出金額是出于什么考慮?
實時效率更高,預(yù)算才效率低下。預(yù)算還要占額外存儲。因為紅包只占一條記錄而且有效期就幾天,所以不需要多大空間。就算壓力大時,水平擴(kuò)展機(jī)器是。