需求背景
? ? ? 我們app和對接單位擬舉行一次抽獎活動提高日活,app內(nèi)提供抽獎入口頁面,進入抽獎頁面點擊賺取積分進入第三方頁面,進行答題,賺取積分。抽獎規(guī)則:每個人每天最多抽獎3次,每次抽獎消耗積分3分,活動期間每個人最大中獎次數(shù)是固定的,每次的中獎概率也是不同的。以上所有的配置都支持動態(tài)配置即修改動配置立即生效,無須重啟應(yīng)用。
架構(gòu)設(shè)計
結(jié)合此需求前提下,采用springboot+mybatisplus+nacos+分布式鎖+redis隊列來實現(xiàn)抽獎功能,并且由springcloud網(wǎng)關(guān)來實現(xiàn)抽獎接口數(shù)據(jù)加解密以及限流功能,防止有人惡意刷票導(dǎo)致系統(tǒng)崩潰
詳細設(shè)計
由于獎品數(shù)量不大,且獎品不區(qū)分等級,因此系統(tǒng)初始化時將獎品緩存到redis隊列中,并設(shè)置獎品池標(biāo)識true/false(true代表還有獎品,false代表無獎品)。此處由于系統(tǒng)是集群部署,因此在初始化獎品池的過程添加了分布式鎖,防止初始化多次獎品池數(shù)據(jù)。
抽獎接口防冪等性:抽獎之前先針對用戶生成唯一token,將該token放入header中請求抽獎接口
另外注意的點就是防超賣,除了前面正常判斷是否滿足抽獎資格邏輯之外,扣庫存操作借助消息隊列線性消費,消費者在扣減庫存時,采用行鎖的方式扣減庫存,update? xx set count=count-1 where id = xxx and? count>1,而不是先select 再update(容易引起并發(fā)問題) ,另外扣減庫存操作假如失敗,需要回填庫存
另外針對抽獎接口,添加了限流邏輯,實現(xiàn)機制是基于RateLimter的令牌桶算法,每秒鐘向桶中放x枚令牌,每個請求進來如果拿到令牌則繼續(xù)執(zhí)行,拿不到令牌則返回系統(tǒng)繁忙請稍后重試等提示
以上就是考慮的比較重要的幾點吧,如有不對的地方請指出!