关于微信红包的架构思考
關(guān)于微信紅包的架構(gòu)思考
微信紅包的架構(gòu)實(shí)現(xiàn)是前段時(shí)間技術(shù)圈里很熱門的一個(gè)話題,這是一個(gè)非常典型的大訪問(wèn)高并發(fā)場(chǎng)景。至于如何實(shí)現(xiàn),答案并不是唯一的,對(duì)這個(gè)問(wèn)題的思考其實(shí)反映了工程師的架構(gòu)設(shè)計(jì)功底。所以我也談一談我的想法。
首先任何架構(gòu)設(shè)計(jì)離不開對(duì)業(yè)務(wù)的理解和認(rèn)識(shí),架構(gòu)設(shè)計(jì)并不是憑空存在的,一定是基于業(yè)務(wù)場(chǎng)景并且服務(wù)業(yè)務(wù)場(chǎng)景的。所以我先分析一下微信紅包的業(yè)務(wù)場(chǎng)景。
*** 需要特別說(shuō)一點(diǎn),本文中的架構(gòu)設(shè)計(jì)不一定是官方的實(shí)現(xiàn)方式,只是一種分析,是基于我目前的技術(shù)能力的一種思考 ***
業(yè)務(wù)場(chǎng)景分析
根據(jù)微信紅包的操作,可以把紅包的業(yè)務(wù)場(chǎng)景分為發(fā)放紅包,搶紅包和打開紅包三個(gè)步驟。
PS:我覺得微信紅包的架構(gòu)討論之所以非常火爆,一個(gè)重要原因就是微信紅包的業(yè)務(wù)場(chǎng)景大家都很熟悉
發(fā)放紅包:
- 發(fā)放者設(shè)置紅包金額,紅包數(shù)量等屬性
- 從發(fā)放者賬戶扣除紅包金額
- 生成紅包,并且發(fā)送搶紅包的鏈接
搶紅包:
- 用戶點(diǎn)擊紅包鏈接
打開紅包:
- 顯示用戶搶到的紅包金額
- 剩余紅包數(shù)量-1,紅包剩余金額改變
- 搶到紅包的用戶賬戶金額增加
注意,以上均為原子操作
根據(jù)業(yè)務(wù)場(chǎng)景,可以知道紅包的主要屬性有:
- 紅包金額:始終不變
- 紅包總數(shù)量:始終不變
- 紅包剩余金額:每次有人領(lǐng)取紅包,該屬性變化
- 紅包剩余數(shù)量:每次有人領(lǐng)取紅包,該屬性-1
- 搶到紅包的用戶以及搶到的金額:用于顯示手氣排行,并且防止重復(fù)搶紅包
- 過(guò)期時(shí)間:如果到過(guò)期紅包仍未搶完,返回發(fā)放者賬戶
架構(gòu)分析
單純實(shí)現(xiàn)微信紅包的功能并不復(fù)雜,其難點(diǎn)在于如何處理高訪問(wèn)和并發(fā),當(dāng)發(fā)出一個(gè)紅包之后,只有少數(shù)人能夠搶到,而大部分的請(qǐng)求都屬于無(wú)效請(qǐng)求,如果讓這部分請(qǐng)求落到數(shù)據(jù)庫(kù)或者在服務(wù)端經(jīng)過(guò)復(fù)雜處理,那么以微信的用戶體量,后果是災(zāi)難性的。
從這個(gè)角度來(lái)說(shuō),微信紅包和電商的秒殺業(yè)務(wù)有幾分相似
處理類似業(yè)務(wù)最常見的手段就是請(qǐng)求過(guò)濾和添加緩存(cache),當(dāng)然,至于服務(wù)器集群,負(fù)載均衡,讀寫分離這些基礎(chǔ)架構(gòu),由于已經(jīng)成了大型網(wǎng)站的標(biāo)配,默認(rèn)已經(jīng)存在。
其中,請(qǐng)求過(guò)濾是只允許少數(shù)符合條件的請(qǐng)求走到最后,把大量不符合條件的請(qǐng)求擋在外面,這個(gè)非常關(guān)鍵。而采用緩存技術(shù),原因有兩個(gè),一是緩存的訪問(wèn)速度快,使用緩存可以有效提高吞吐速度,二是紅包發(fā)放相對(duì)來(lái)說(shuō)是一個(gè)臨時(shí)性的東西,故而可以放在緩存里面。
業(yè)務(wù)上需要注意的地方
- 防止用戶重復(fù)搶紅包
- 應(yīng)對(duì)redis宕機(jī)的風(fēng)險(xiǎn),目前一般是采用sentinel機(jī)制
架構(gòu)設(shè)計(jì)
緩存我們默認(rèn)使用redis,數(shù)據(jù)庫(kù)默認(rèn)使用mysql
新建紅包的時(shí)候,生成唯一紅包id,設(shè)置紅包屬性,在mysql中添加記錄,表結(jié)構(gòu)大致如下
|紅包id|發(fā)放者uid|紅包總金額|紅包總數(shù)量|紅包剩余金額|紅包剩余數(shù)量|搶到紅包的用戶列表json|過(guò)期時(shí)間|創(chuàng)建時(shí)間|
|---|:----|:---|---|----|---|---|----|---|--|--|:---|:----|:---|---|----|---|---|----|---|--
同時(shí),在redis里添加:
- 搶紅包請(qǐng)求隊(duì)列(隊(duì)列)
- 打開紅包請(qǐng)求隊(duì)列(隊(duì)列)
- 紅包信息,包含剩余紅包數(shù)量和剩余金額(鍵值對(duì))
- 已經(jīng)搶到紅包的用戶信息(有序集合)
當(dāng)搶紅包的時(shí)候,
做以下判斷:
- 剩余紅包數(shù)量是否大于0
- 該用戶是否在已經(jīng)搶到紅包的用戶集合里面
通過(guò)判斷的請(qǐng)求添加進(jìn)請(qǐng)求隊(duì)列,否則返回已經(jīng)搶完的標(biāo)示,這樣下一步用戶打開紅包的時(shí)候,甚至可以不發(fā)送請(qǐng)求直接顯示紅包已經(jīng)搶完,過(guò)濾無(wú)效請(qǐng)求
于此同時(shí),另外有進(jìn)程從請(qǐng)求隊(duì)列里取出搶紅包請(qǐng)求,生成token標(biāo)示,返回給搶紅包者
當(dāng)用戶打開紅包的時(shí)候,傳入該標(biāo)示,放進(jìn)打開紅包請(qǐng)求隊(duì)列,后端消費(fèi)者進(jìn)程從隊(duì)列中取出打開紅包請(qǐng)求,判斷紅包數(shù)量是否大于0,以及用戶傳來(lái)的打開紅包token與紅包id是否合法,參數(shù)檢驗(yàn)之后,生成紅包金額,調(diào)用余額接口處理,并且更新redis中紅包剩余數(shù)量,紅包剩余金額
最后異步方式更新數(shù)據(jù)庫(kù)
紅包算法
關(guān)于紅包算法,網(wǎng)上說(shuō)的很多了,這里就不啰嗦了,金額是拆的時(shí)候?qū)崟r(shí)算出來(lái),不是預(yù)先分配的,采用的是純內(nèi)存計(jì)算,不需要預(yù)算空間存儲(chǔ),具體的算法是在在0.01和剩余平均值的2倍之間隨機(jī)生成一個(gè)金額
效果
比如現(xiàn)在發(fā)了一個(gè)紅包,分為5份。有100個(gè)人搶。
可能有10個(gè)人成功進(jìn)入請(qǐng)求隊(duì)列(搶到紅包和打開紅包之間有一定間隔,所以先搶到的不一定先打開),拿到了打開紅包token,其余90個(gè)人拿到的是紅包已經(jīng)搶完的token,那么當(dāng)打開紅包的時(shí)候,這90個(gè)人甚至都不需要發(fā)送請(qǐng)求,直接顯示紅包已搶完
這10個(gè)人打開紅包的時(shí)候,其中5個(gè)人搶到,剩下的5個(gè)也顯示紅包已經(jīng)搶完
本來(lái)5個(gè)紅包100個(gè)人搶,會(huì)請(qǐng)求201次(生成紅包1次+搶紅包100次+打開紅包100次)
那么這種情況下,只需要111次(生成紅包1次+搶紅包100次+打開紅包10次),并且,其中90次請(qǐng)求很快就返回,大大減輕服務(wù)端壓力
需要注意的是
- 如何保證原子性操作
- 如何提高可用性,主要是防止redis宕機(jī)
總結(jié)
衡量一個(gè)架構(gòu)設(shè)計(jì)的標(biāo)準(zhǔn)主要是性能,擴(kuò)展性,伸縮性,可用性,安全性等指標(biāo),本例中,由于紅包業(yè)務(wù)是一個(gè)很具體的業(yè)務(wù),并非通用服務(wù),所以不討論擴(kuò)展性。
- 性能角度,由于采用了緩存以及請(qǐng)求過(guò)濾等手段,性能肯定比常規(guī)實(shí)現(xiàn)大大提高
- 伸縮性角度,應(yīng)該采用服務(wù)器集群,redis集群,mysql集群的方式部署,注意redis集群中的一致性hash的實(shí)現(xiàn)
- 可用性角度,本例中決定可用性的關(guān)鍵還是在于redis集群是否能夠保證高可用,所以sentinel機(jī)制必不可少,甚至還應(yīng)該加上其他的各種檢測(cè)節(jié)點(diǎn),替換節(jié)點(diǎn)方案,以保證高可用。而且需要考慮極端情況,例如緩存被擊穿導(dǎo)致mysql壓力過(guò)大的情況下,如何確保服務(wù)不宕機(jī)。
- 安全性角度,紅包涉及資金來(lái)往,所以需要格外注意安全性。紅包業(yè)務(wù)中,是通過(guò)調(diào)用接口來(lái)實(shí)現(xiàn)資金往來(lái),故賬目平衡的風(fēng)險(xiǎn)不是由紅包系統(tǒng)來(lái)承擔(dān)而是由紅包所調(diào)用的接口保證的,但紅包系統(tǒng)也可能存在以下幾種安全隱患,單一用戶重復(fù)搶紅包,所有用戶搶的的紅包金額總數(shù)大于發(fā)放者設(shè)置的紅包金額等。所以其關(guān)鍵在于確保搶紅包,打開紅包均為一次原子性操作。如有必要,甚至可以通過(guò)加鎖等方式實(shí)現(xiàn),但需要考慮加鎖對(duì)于性能上的影響
作者:cuihang
鏈接:https://www.jianshu.com/p/63f238b04c59
來(lái)源:簡(jiǎn)書
簡(jiǎn)書著作權(quán)歸作者所有,任何形式的轉(zhuǎn)載都請(qǐng)聯(lián)系作者獲得授權(quán)并注明出處。
總結(jié)
以上是生活随笔為你收集整理的关于微信红包的架构思考的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 谈谈我对服务熔断、服务降级的理解
- 下一篇: 微信红包的支撑架构原理是什么?