關(guān)于微信紅包的架構(gòu)思考

關(guān)于微信紅包的架構(gòu)思考

微信紅包的架構(gòu)實現(xiàn)是前段時間技術(shù)圈里很熱門的一個話題,這是一個非常典型的大訪問高并發(fā)場景狼荞。至于如何實現(xiàn)胁镐,答案并不是唯一的,對這個問題的思考其實反映了工程師的架構(gòu)設(shè)計功底华望。所以我也談一談我的想法。

首先任何架構(gòu)設(shè)計離不開對業(yè)務(wù)的理解和認(rèn)識仅乓,架構(gòu)設(shè)計并不是憑空存在的赖舟,一定是基于業(yè)務(wù)場景并且服務(wù)業(yè)務(wù)場景的。所以我先分析一下微信紅包的業(yè)務(wù)場景夸楣。


*** 需要特別說一點宾抓,本文中的架構(gòu)設(shè)計不一定是官方的實現(xiàn)方式,只是一種分析豫喧,是基于我目前的技術(shù)能力的一種思考 ***


業(yè)務(wù)場景分析

根據(jù)微信紅包的操作石洗,可以把紅包的業(yè)務(wù)場景分為發(fā)放紅包,搶紅包和打開紅包三個步驟紧显。
PS:我覺得微信紅包的架構(gòu)討論之所以非辰采溃火爆,一個重要原因就是微信紅包的業(yè)務(wù)場景大家都很熟悉

發(fā)放紅包:
  • 發(fā)放者設(shè)置紅包金額孵班,紅包數(shù)量等屬性
  • 從發(fā)放者賬戶扣除紅包金額
  • 生成紅包涉兽,并且發(fā)送搶紅包的鏈接
搶紅包:
  • 用戶點擊紅包鏈接
打開紅包:
  • 顯示用戶搶到的紅包金額
  • 剩余紅包數(shù)量-1,紅包剩余金額改變
  • 搶到紅包的用戶賬戶金額增加

注意篙程,以上均為原子操作

根據(jù)業(yè)務(wù)場景枷畏,可以知道紅包的主要屬性有:

  • 紅包金額:始終不變
  • 紅包總數(shù)量:始終不變
  • 紅包剩余金額:每次有人領(lǐng)取紅包,該屬性變化
  • 紅包剩余數(shù)量:每次有人領(lǐng)取紅包虱饿,該屬性-1
  • 搶到紅包的用戶以及搶到的金額:用于顯示手氣排行拥诡,并且防止重復(fù)搶紅包
  • 過期時間:如果到過期紅包仍未搶完触趴,返回發(fā)放者賬戶

架構(gòu)分析

單純實現(xiàn)微信紅包的功能并不復(fù)雜,其難點在于如何處理高訪問和并發(fā)渴肉,當(dāng)發(fā)出一個紅包之后冗懦,只有少數(shù)人能夠搶到,而大部分的請求都屬于無效請求宾娜,如果讓這部分請求落到數(shù)據(jù)庫或者在服務(wù)端經(jīng)過復(fù)雜處理批狐,那么以微信的用戶體量,后果是災(zāi)難性的前塔。

從這個角度來說嚣艇,微信紅包和電商的秒殺業(yè)務(wù)有幾分相似

處理類似業(yè)務(wù)最常見的手段就是請求過濾和添加緩存(cache),當(dāng)然华弓,至于服務(wù)器集群食零,負(fù)載均衡,讀寫分離這些基礎(chǔ)架構(gòu)寂屏,由于已經(jīng)成了大型網(wǎng)站的標(biāo)配贰谣,默認(rèn)已經(jīng)存在。

其中迁霎,請求過濾是只允許少數(shù)符合條件的請求走到最后吱抚,把大量不符合條件的請求擋在外面,這個非常關(guān)鍵考廉。而采用緩存技術(shù)秘豹,原因有兩個,一是緩存的訪問速度快昌粤,使用緩存可以有效提高吞吐速度既绕,二是紅包發(fā)放相對來說是一個臨時性的東西,故而可以放在緩存里面涮坐。

業(yè)務(wù)上需要注意的地方

  • 防止用戶重復(fù)搶紅包
  • 應(yīng)對redis宕機的風(fēng)險凄贩,目前一般是采用sentinel機制

架構(gòu)設(shè)計

緩存我們默認(rèn)使用redis,數(shù)據(jù)庫默認(rèn)使用mysql

新建紅包的時候袱讹,生成唯一紅包id疲扎,設(shè)置紅包屬性,在mysql中添加記錄捷雕,表結(jié)構(gòu)大致如下

|紅包id|發(fā)放者uid|紅包總金額|紅包總數(shù)量|紅包剩余金額|紅包剩余數(shù)量|搶到紅包的用戶列表json|過期時間|創(chuàng)建時間|
|---|:----|:---|---|----|---|---|----|---|--|--|:---|:----|:---|---|----|---|---|----|---|--

同時椒丧,在redis里添加:

  • 搶紅包請求隊列(隊列)
  • 打開紅包請求隊列(隊列)
  • 紅包信息,包含剩余紅包數(shù)量和剩余金額(鍵值對)
  • 已經(jīng)搶到紅包的用戶信息(有序集合)

當(dāng)搶紅包的時候非区,
做以下判斷:

  • 剩余紅包數(shù)量是否大于0
  • 該用戶是否在已經(jīng)搶到紅包的用戶集合里面
    通過判斷的請求添加進(jìn)請求隊列瓜挽,否則返回已經(jīng)搶完的標(biāo)示盹廷,這樣下一步用戶打開紅包的時候征绸,甚至可以不發(fā)送請求直接顯示紅包已經(jīng)搶完,過濾無效請求

于此同時,另外有進(jìn)程從請求隊列里取出搶紅包請求管怠,生成token標(biāo)示淆衷,返回給搶紅包者

當(dāng)用戶打開紅包的時候,傳入該標(biāo)示渤弛,放進(jìn)打開紅包請求隊列祝拯,后端消費者進(jìn)程從隊列中取出打開紅包請求,判斷紅包數(shù)量是否大于0她肯,以及用戶傳來的打開紅包token與紅包id是否合法佳头,參數(shù)檢驗之后,生成紅包金額晴氨,調(diào)用余額接口處理康嘉,并且更新redis中紅包剩余數(shù)量,紅包剩余金額

最后異步方式更新數(shù)據(jù)庫

紅包算法

關(guān)于紅包算法籽前,網(wǎng)上說的很多了亭珍,這里就不啰嗦了,金額是拆的時候?qū)崟r算出來枝哄,不是預(yù)先分配的肄梨,采用的是純內(nèi)存計算,不需要預(yù)算空間存儲挠锥,具體的算法是在在0.01和剩余平均值的2倍之間隨機生成一個金額

效果

比如現(xiàn)在發(fā)了一個紅包众羡,分為5份。有100個人搶瘪贱。

可能有10個人成功進(jìn)入請求隊列(搶到紅包和打開紅包之間有一定間隔纱控,所以先搶到的不一定先打開),拿到了打開紅包token菜秦,其余90個人拿到的是紅包已經(jīng)搶完的token甜害,那么當(dāng)打開紅包的時候,這90個人甚至都不需要發(fā)送請求球昨,直接顯示紅包已搶完

這10個人打開紅包的時候尔店,其中5個人搶到,剩下的5個也顯示紅包已經(jīng)搶完

本來5個紅包100個人搶主慰,會請求201次(生成紅包1次+搶紅包100次+打開紅包100次)
那么這種情況下嚣州,只需要111次(生成紅包1次+搶紅包100次+打開紅包10次),并且共螺,其中90次請求很快就返回该肴,大大減輕服務(wù)端壓力

需要注意的是

  • 如何保證原子性操作
  • 如何提高可用性,主要是防止redis宕機

總結(jié)

衡量一個架構(gòu)設(shè)計的標(biāo)準(zhǔn)主要是性能藐不,擴展性匀哄,伸縮性秦效,可用性,安全性等指標(biāo)涎嚼,本例中阱州,由于紅包業(yè)務(wù)是一個很具體的業(yè)務(wù),并非通用服務(wù)法梯,所以不討論擴展性苔货。

  • 性能角度,由于采用了緩存以及請求過濾等手段立哑,性能肯定比常規(guī)實現(xiàn)大大提高
  • 伸縮性角度夜惭,應(yīng)該采用服務(wù)器集群,redis集群铛绰,mysql集群的方式部署滥嘴,注意redis集群中的一致性hash的實現(xiàn)
  • 可用性角度,本例中決定可用性的關(guān)鍵還是在于redis集群是否能夠保證高可用至耻,所以sentinel機制必不可少若皱,甚至還應(yīng)該加上其他的各種檢測節(jié)點,替換節(jié)點方案尘颓,以保證高可用走触。而且需要考慮極端情況,例如緩存被擊穿導(dǎo)致mysql壓力過大的情況下疤苹,如何確保服務(wù)不宕機互广。
  • 安全性角度,紅包涉及資金來往卧土,所以需要格外注意安全性惫皱。紅包業(yè)務(wù)中,是通過調(diào)用接口來實現(xiàn)資金往來尤莺,故賬目平衡的風(fēng)險不是由紅包系統(tǒng)來承擔(dān)而是由紅包所調(diào)用的接口保證的旅敷,但紅包系統(tǒng)也可能存在以下幾種安全隱患,單一用戶重復(fù)搶紅包颤霎,所有用戶搶的的紅包金額總數(shù)大于發(fā)放者設(shè)置的紅包金額等媳谁。所以其關(guān)鍵在于確保搶紅包,打開紅包均為一次原子性操作友酱。如有必要晴音,甚至可以通過加鎖等方式實現(xiàn),但需要考慮加鎖對于性能上的影響
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末缔杉,一起剝皮案震驚了整個濱河市锤躁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌或详,老刑警劉巖系羞,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件加缘,死亡現(xiàn)場離奇詭異,居然都是意外死亡觉啊,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進(jìn)店門沈贝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來杠人,“玉大人,你說我怎么就攤上這事宋下∥松疲” “怎么了?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵学歧,是天一觀的道長罩引。 經(jīng)常有香客問我,道長枝笨,這世上最難降的妖魔是什么袁铐? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮横浑,結(jié)果婚禮上剔桨,老公的妹妹穿的比我還像新娘。我一直安慰自己徙融,他們只是感情好洒缀,可當(dāng)我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著欺冀,像睡著了一般树绩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上隐轩,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天饺饭,我揣著相機與錄音,去河邊找鬼职车。 笑死砰奕,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的提鸟。 我是一名探鬼主播军援,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼称勋!你這毒婦竟也來了胸哥?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤赡鲜,失蹤者是張志新(化名)和其女友劉穎空厌,沒想到半個月后庐船,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡嘲更,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年筐钟,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赋朦。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡篓冲,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出宠哄,到底是詐尸還是另有隱情壹将,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布毛嫉,位于F島的核電站诽俯,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏承粤。R本人自食惡果不足惜暴区,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望辛臊。 院中可真熱鬧颜启,春花似錦、人聲如沸浪讳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽淹遵。三九已至口猜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間透揣,已是汗流浹背济炎。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留辐真,地道東北人须尚。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像侍咱,于是被迫代替她去往敵國和親耐床。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,446評論 2 348

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

  • 4后臺 4.1 數(shù)據(jù)庫 以下關(guān)系型數(shù)據(jù)庫設(shè)計的字段是基于少量請求下楔脯,我們模擬紅包系統(tǒng)的可行方案撩轰,并沒有考慮高并發(fā)、...
    瑞爾惠閱讀 1,734評論 0 2
  • 倒計時3天咯!媽呀好快好快堪嫂,堅持住啊加油 每一天都有特別大的收獲偎箫,感恩這次特種兵,我成長了很多皆串。每天的好習(xí)慣真的是...
    茗煜閱讀 160評論 0 0
  • 舉頭三尺有神明淹办,明明你就很癡情,情根深種已入刑恶复,刑后多情成墓銘怜森。
    litreily閱讀 422評論 1 1
  • 別讓瑣事牽著鼻子走 通過這個第四代時間管理矩形圖我們能夠?qū)r間分配有一個很好的理解。 緊迫/緊急意味著必須...
    Betty_曉芳閱讀 509評論 4 2