導讀
前二天我寫了一篇,Redis高階專案實戰(點我直達),SpringBoot整合Redis附原始碼(點我直達),今天我們來做一下Redis秒殺系統的設計。當然啦,Redis基礎知識還不過關的,先去加強下自身內功,然後在回來看這篇,Redis基礎知識(點我直達)。為啥寫這個微信搶紅包專案呢,公司0202年08月22日,公司週年慶,搶了100多紅包?,O(∩_∩)O哈哈~
微信搶紅包實現原理
業務流程分析
功能拆解
新建紅包
在DB、Redis分別新增一條記錄
搶紅包(併發)
請求Redis,紅包剩餘個數,大於0才可以拆,等會0時,提示使用者,紅包已搶完
拆紅包(併發)
用到技術
Redis中資料型別的String特性的原子遞減(DECR key)和減少指定值(DECRBY key decrement)
業務
- 請求Redis,當剩餘紅包個數大於0,紅包個數原子遞減,隨機獲取紅包
- 計算金額,當最後一個紅包時,最後一個紅包金額=總金額-總已搶紅包金額
- 更新資料庫
檢視紅包記錄
查詢DB即可
資料庫表設計
紅包流水錶
CREATE TABLE `red_packet_info` ( `id` int(11) NOT NULL AUTO_INCREMENT, `red_packet_id` bigint(11) NOT NULL DEFAULT 0 COMMENT '紅包id,採⽤ timestamp+5位隨機數', `total_amount` int(11) NOT NULL DEFAULT 0 COMMENT '紅包總⾦額,單位分', `total_packet` int(11) NOT NULL DEFAULT 0 COMMENT '紅包總個數', `remaining_amount` int(11) NOT NULL DEFAULT 0 COMMENT '剩餘紅包⾦額,單位 分', `remaining_packet` int(11) NOT NULL DEFAULT 0 COMMENT '剩餘紅包個數', `uid` int(20) NOT NULL DEFAULT 0 COMMENT '新建紅包⽤戶的⽤戶標識', `create_time` timestamp COMMENT '建立時間', `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時間', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='紅包資訊 表,新建⼀個紅包插⼊⼀條記錄';
紅包記錄表
CREATE TABLE `red_packet_record` ( `id` int(11) NOT NULL AUTO_INCREMENT, `amount` int(11) NOT NULL DEFAULT '0' COMMENT '搶到紅包的⾦額', `nick_name` varchar(32) NOT NULL DEFAULT '0' COMMENT '搶到紅包的⽤戶的⽤戶 名', `img_url` varchar(255) NOT NULL DEFAULT '0' COMMENT '搶到紅包的⽤戶的頭像', `uid` int(20) NOT NULL DEFAULT '0' COMMENT '搶到紅包⽤戶的⽤戶標識', `red_packet_id` bigint(11) NOT NULL DEFAULT '0' COMMENT '紅包id,採⽤ timestamp+5位隨機數', `create_time` timestamp COMMENT '建立時間', `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時間', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='搶紅包記 錄表,搶⼀個紅包插⼊⼀條記錄';
發紅包API
發紅包介面開發
- 新增一條紅包記錄
- 往mysql裡面添加一條紅包記錄
- 往redis裡面添加一條紅包數量記錄
- 往redis裡面添加一條紅包金額記錄
注意,往db中就單純存入一條記錄,Service層和Mapper層,就簡單的一條sql語句,主要是提供思路,下面會附案例原始碼,不要慌
搶紅包API
- 搶紅包功能屬於原子減操作
- 當大小小於0時原子減失敗
- 當紅包個數為0時,後面進來的使用者全部搶紅包失敗,並不會進入拆紅包環節
- 搶紅包功能設計
- 將紅包ID的請求放入請求佇列中,如果發現超過紅包的個數,直接返回
- 注意事項
- 搶到紅包不一定能拆成功
搶紅包演算法拆解
通過上圖演算法得出,靠前面的人,手氣最佳機率小,手氣最佳,往往在後面
- 發100元,共10個紅包,那麼平均值是10元一個,那麼發出來的紅包金額在0.01~20元之間波動
- 當前面4個紅包總共被領了30元時,剩下70元,總共6個紅包,那麼這6個紅包的金額在0.01~23.3元之間波動
搶紅包介面開發
測試
發紅包
模擬高併發搶紅包(Jmeter壓測工具)
因為我發了10個紅包,金額是20000,使用壓測工具,模擬50個請求,只允許前10個請求能搶到紅包,並且金額等於20000。
專案原始碼下載
連結: https://pan.baidu.com/s/1knmVMKBldVe46cmXqqfGpw 密碼: a7o7
未完待續
微信上有個小夥伴剛好要做一個秒殺的系統,催我趕緊把部落格更新出來。過2天繼續往下更新,布隆過濾器。