微信紅包實現(xiàn)原理探討

一、背景

以下內(nèi)容基于QCon某高可用架構(gòu)群討論總結(jié)

群里某同學(xué)問起微信紅包架構(gòu)筷黔,騰訊財付通同學(xué)作出解答佛舱,以下實現(xiàn)原理根據(jù)對話內(nèi)容推導(dǎo)得出,不代表官方實現(xiàn)订歪。

實現(xiàn)方式千百種肆捕,不追求方法復(fù)制,只追求推導(dǎo)過程的思考總結(jié)眼虱。最后轉(zhuǎn)了新浪微博Tim總的另一種實現(xiàn)方式席纽。

二胆筒、微信紅包實現(xiàn)原理

關(guān)鍵設(shè)計

  • 通過cache抵擋大部分請求(是否能拆紅包等)
  • DB使用CAS操作更新紅包計數(shù)記錄
  • DB、cache使用sharding抒和,可水平擴展

1. 新建紅包

  • 在DB彤蔽、cache各新增一條記錄

2. 搶紅包

  • 請求訪問cache,剩余紅包個數(shù)大于0則可拆開紅包

3. 拆紅包

  • 請求訪問cache镊辕,剩余紅包個數(shù)大于0則繼續(xù),同時獲取可搶紅包數(shù)與金額
  • 計算金額(從1分到剩余平均值2倍之間隨機數(shù)石咬,如果不是最后一個紅包卖哎,剩余金額預(yù)留最少1分給cas更新失敗亏娜,最后一位拿紅包的人)
  • cas更新數(shù)據(jù)庫(更新紅包計數(shù)表記錄【剩余紅包個數(shù)、剩余紅包金額】它掂、插入領(lǐng)取記錄)
    • 更新失敗溯泣,重復(fù)以上操作,直到更新成功或已領(lǐng)取完
    • 更新成功熟妓,更新緩存

DB實現(xiàn)CAS操作偽代碼(說明作用):

while (hadHongBao()) {
    //剩余紅包個數(shù)
    def remainCount = getRemainCount() 
    //實時計算獲取紅包金額
    def getAmount = calculateAmount() 
    def result = sql.excute("update '紅包計算表' set balance=${total-getAmount}, remainCount=${remainCount-1} where remainCount=${remainCount} and id=${id}")
    // 更新失敗既繼續(xù)執(zhí)行循環(huán),直到更新成功或已領(lǐng)取完只恨,達(dá)到CAS效果
    if (result > 0) {
        // 更新成功官觅,執(zhí)行更新緩存等后續(xù)操作
        // ......
        break
    }
}

DB、cache主要數(shù)據(jù)結(jié)構(gòu)

  1. DB:紅包計數(shù)表【主要字段:紅包總金額咱圆、紅包總個數(shù)功氨、剩余紅包個數(shù)、剩余紅包金額】
  2. cache:紅包計數(shù)記錄【主要字段:剩余紅包個數(shù)忱详、剩余紅包金額】

其他補充

注:DB匈睁、cache使用sharding,訪問量增大胀蛮,DB糯钙、cache、服務(wù)端都可水平擴展鸳玩。

三演闭、FAQ

上述內(nèi)容講解了搶紅包關(guān)鍵實現(xiàn)原理,更多其他細(xì)節(jié)請看下述群記錄摘要(以下內(nèi)容轉(zhuǎn)載自:https://www.zybuluo.com/yulin718/note/93148

  1. 微信的金額什么時候算窝革?
    答:微信金額是拆的時候?qū)崟r算出來吕座,不是預(yù)先分配的吴趴,采用的是純內(nèi)存計算,不需要預(yù)算空間存儲厢拭。撇叁。
    采取實時計算金額的考慮:預(yù)算需要占存儲,實時效率很高楞捂,預(yù)算才效率低趋厉。

  2. 實時性:為什么明明搶到紅包觅廓,點開后發(fā)現(xiàn)沒有?
    答:2014年的紅包一點開就知道金額帖蔓,分兩次操作矮瘟,先搶到金額,然后再轉(zhuǎn)賬塑娇。
    2015年的紅包的拆和搶是分離的澈侠,需要點兩次,因此會出現(xiàn)搶到紅包了埋酬,但點開后告知紅包已經(jīng)被領(lǐng)完的狀況哨啃。進入到第一個頁面不代表搶到,只表示當(dāng)時紅包還有写妥。

  3. 分配:紅包里的金額怎么算拳球?為什么出現(xiàn)各個紅包金額相差很大?
    答:隨機珍特,額度在0.01和剩余平均值2之間祝峻。
    例如:發(fā)100塊錢扎筒,總共10個紅包莱找,那么平均值是10塊錢一個,那么發(fā)出來的紅包的額度在0.01元~20元之間波動嗜桌。
    當(dāng)前面3個紅包總共被領(lǐng)了40塊錢時奥溺,剩下60塊錢,總共7個紅包骨宠,那么這7個紅包的額度在:0.01~(60/7
    2)=17.14之間浮定。
    注意:這里的算法是每被搶一個后,剩下的會再次執(zhí)行上面的這樣的算法(Tim老師也覺得上述算法太復(fù)雜诱篷,不知基于什么樣的考慮)壶唤。
    這樣算下去雳灵,會超過最開始的全部金額棕所,因此到了最后面如果不夠這么算,那么會采取如下算法:保證剩余用戶能拿到最低1分錢即可悯辙。
    如果前面的人手氣不好琳省,那么后面的余額越多,紅包額度也就越多躲撰,因此實際概率一樣的针贬。

  4. 紅包的設(shè)計
    答:微信從財付通拉取金額數(shù)據(jù)郭萊,生成個數(shù)/紅包類型/金額放到redis集群里拢蛋,app端將紅包ID的請求放入請求隊列中桦他,如果發(fā)現(xiàn)超過紅包的個數(shù),直接返回谆棱。根據(jù)紅包的裸祭處理成功得到令牌請求快压,則由財付通進行一致性調(diào)用圆仔,通過像比特幣一樣,兩邊保存交易記錄蔫劣,交易后交給第三方服務(wù)審計坪郭,如果交易過程中出現(xiàn)不一致就強制回歸。

  5. 高并發(fā)處理:紅包如何計算被搶完脉幢?
    答:cache會抵抗無效請求歪沃,將無效的請求過濾掉,實際進入到后臺的量不大嫌松。cache記錄紅包個數(shù)沪曙,原子操作進行個數(shù)遞減,到0表示被搶光萎羔。財付通按照20萬筆每秒入賬準(zhǔn)備珊蟀,但實際還不到8萬每秒。

  6. 通如何保持8w每秒的寫入外驱?
    答:多主sharding育灸,水平擴展機器。

  7. 據(jù)容量多少昵宇?
    答:一個紅包只占一條記錄磅崭,有效期只有幾天,因此不需要太多空間瓦哎。

  8. 詢紅包分配砸喻,壓力大不?
    答:搶到紅包的人數(shù)和紅包都在一條cache記錄上蒋譬,沒有太大的查詢壓力割岛。

  9. 一個紅包一個隊列?
    答:沒有隊列犯助,一個紅包一條數(shù)據(jù)癣漆,數(shù)據(jù)上有一個計數(shù)器字段。

  10. 有沒有從數(shù)據(jù)上證明每個紅包的概率是不是均等剂买?
    答:不是絕對均等惠爽,就是一個簡單的拍腦袋算法。

  11. 拍腦袋算法瞬哼,會不會出現(xiàn)兩個最佳婚肆?
    答:會出現(xiàn)金額一樣的,但是手氣最佳只有一個坐慰,先搶到的那個最佳较性。

  12. 每領(lǐng)一個紅包就更新數(shù)據(jù)么?
    答:每搶到一個紅包,就cas更新剩余金額和紅包個數(shù)赞咙。

  13. 紅包如何入庫入賬永毅?
    數(shù)據(jù)庫會累加已經(jīng)領(lǐng)取的個數(shù)與金額,插入一條領(lǐng)取記錄人弓。入賬則是后臺異步操作沼死。

  14. 入帳出錯怎么辦?比如紅包個數(shù)沒了崔赌,但余額還有意蛀?
    答:最后會有一個take all操作。另外還有一個對賬來保障健芭。

四县钥、另一種實現(xiàn)

群里討論實現(xiàn)原理時,多人提出預(yù)分配金額的實現(xiàn)方式(新建紅包時已分配好每一位搶到紅包的金額)慈迈,減少實時計算及CAS操作的性能損耗若贮,財付通同學(xué)說到預(yù)分配金額還需要額外存儲空間(更重要的可能是現(xiàn)在的實現(xiàn)方式已滿足需求),后來新浪微博Tim總提出預(yù)分配方式不占用額外存儲空間的方式痒留,詳細(xì)請看:
<a >微信紅包金額分配的算法</a>

實現(xiàn)原理

  • 通過保存random seed達(dá)到預(yù)分配金額效果谴麦,既無需記錄剩余紅包金額,只需記錄紅包剩余數(shù)
  • 搶紅包時伸头,針對紅包剩余數(shù)進行DESC原子操作匾效,當(dāng)紅包剩余數(shù)為0既搶完
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市恤磷,隨后出現(xiàn)的幾起案子面哼,更是在濱河造成了極大的恐慌,老刑警劉巖扫步,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件魔策,死亡現(xiàn)場離奇詭異,居然都是意外死亡河胎,警方通過查閱死者的電腦和手機闯袒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來仿粹,“玉大人搁吓,你說我怎么就攤上這事】岳” “怎么了?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵擂橘,是天一觀的道長晌区。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么朗若? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任恼五,我火速辦了婚禮,結(jié)果婚禮上哭懈,老公的妹妹穿的比我還像新娘灾馒。我一直安慰自己,他們只是感情好遣总,可當(dāng)我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布睬罗。 她就那樣靜靜地躺著,像睡著了一般旭斥。 火紅的嫁衣襯著肌膚如雪容达。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天垂券,我揣著相機與錄音花盐,去河邊找鬼。 笑死菇爪,一個胖子當(dāng)著我的面吹牛算芯,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播凳宙,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼也祠,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了近速?” 一聲冷哼從身側(cè)響起诈嘿,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎削葱,沒想到半個月后奖亚,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡析砸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年昔字,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片首繁。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡作郭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出弦疮,到底是詐尸還是另有隱情夹攒,我是刑警寧澤,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布胁塞,位于F島的核電站咏尝,受9級特大地震影響压语,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜编检,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一胎食、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧允懂,春花似錦厕怜、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至谤专,卻和暖如春躁锡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背置侍。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工映之, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蜡坊。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓杠输,卻偏偏與公主長得像,于是被迫代替她去往敵國和親秕衙。 傳聞我的和親對象是個殘疾皇子蠢甲,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,077評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 4后臺 4.1 數(shù)據(jù)庫 以下關(guān)系型數(shù)據(jù)庫設(shè)計的字段是基于少量請求下,我們模擬紅包系統(tǒng)的可行方案据忘,并沒有考慮高并發(fā)鹦牛、...
    瑞爾惠閱讀 1,740評論 0 2
  • ——先生,您要什么勇吊? ——一份田螺曼追。 ——您好,沒有田螺了汉规。 ——走礼殊,咱們?nèi)e處。 我雷厲風(fēng)行针史,轉(zhuǎn)身就走晶伦。 她失落...
    入江楓閱讀 545評論 2 0
  • 來也空空,去也空空啄枕,但人卻活的并不輕松婚陪。多少掛念,幾多勞累射亏,為哪般
    夢在心頭閱讀 159評論 0 0
  • 20161025 早上出門前干了很多事:手洗了襪子近忙、洗衣機洗衣服竭业、折了兩床被子智润、掃了地及舍。還專門拿一個塑料袋裝了冬棗...
    蕭蕭依舊閱讀 161評論 0 0