相關(guān)技術(shù)
Redis是一個開源的使用ANSI C語言編寫辜膝,支持網(wǎng)絡(luò)、可基于內(nèi)存亦可持久化的娱仔、日志型的KV數(shù)據(jù)庫,Redis提供多種語言API游桩。從2010年3年15日起牲迫,Redis的開發(fā)工作由VMware主持并由Pivotal贊助耐朴。
為什么要使用Redis
- 速度快
單節(jié)點(diǎn)每秒可處理10W次請求,具體和機(jī)器配置相關(guān)盹憎。Redis對外提供的服務(wù)為單線程筛峭,采用了多路復(fù)用的方式較快的速度。 - 持久化
- Value值支持多種數(shù)據(jù)類型
hash陪每、list影晓、set、map... - 支持多種編程語言
- 功能豐富
- 主從復(fù)制
- 高可用及分布式
Redis使用KV鍵值對檩禾,其中key為字符串挂签,value具有5種類型:
- List列表類型
# 向key鍵添加v1 v2 v3三個數(shù)據(jù)
lpush key v1 v2 v3...
# 計(jì)算key鍵的個數(shù)
llen key
# 獲取key鍵末尾節(jié)點(diǎn)并從list上刪除
rpop key
- Hash哈希類型
# 設(shè)置鍵名為key的hash數(shù)據(jù)
hset key field value
# 檢查鍵名為key的某個字段是否有值
hexists key field
Redis的弱事務(wù)操作
為什么選擇Lua實(shí)現(xiàn)核心業(yè)務(wù)
Lua是一個小巧的腳本語言,由標(biāo)準(zhǔn)ANSI C語言編寫盼产,Lua解釋器不超過200K饵婆,是目前最快的腳本引擎。Lua語言提供數(shù)據(jù)操作的原子性戏售。Lua腳本的特點(diǎn)是要么操作全部成功侨核,要么操作全部失敗,可彌補(bǔ)Redis的弱事務(wù)灌灾。
流程設(shè)計(jì)
- 將所有紅包全部存儲到redis搓译,也就是紅包池子。
- 用戶搶了多少個紅包锋喜,記錄紅包被搶的詳細(xì)數(shù)據(jù)些己。
- 用戶只能搶一次紅包,不能重復(fù)搶紅包跑芳。
如何將多個紅包放到隊(duì)列中轴总,用來初始化紅包池子。
# 放入紅包:將多個紅包放入list隊(duì)列
lpush redbagPool {rid:1001, money:1}
lpush redbagPool {rid:1002, money:2}
lpush redbagPool {rid:1003, money:3}
# 搶紅包:按順序從隊(duì)列依次彈出
rpop redbagPool
如何記錄用戶和搶了多少錢
# 記錄用戶搶紅包記錄
lpush redbagUser {rid:1001, money:1, userid:101, create_time:'2019-92-16 12:00:00'}
lpush redbagUser {rid:1002, money:2, userid:102, create_time:'2019-92-16 12:00:00' }
lpush redbagUser {rid:1003, money:3, userid:103, create_time:'2019-92-16 12:00:00'}
如何記錄當(dāng)前哪些用戶已經(jīng)搶過紅包博个,防止重復(fù)搶怀樟?
# 將已經(jīng)搶過紅包的用戶加入黑名單
hset redbagBlacklist 101 1001
hset redbagBlacklist 102 1002
hset redbagBlacklist 103 1003
# 檢查是否有重復(fù)記錄若返回1則表示已經(jīng)存在
hexists redbagBlacklist 101
實(shí)現(xiàn)步驟
- Redis初始化紅包
# 將多個紅包數(shù)據(jù)存入redbagPool列表中
plush redbagPool {rid:1001, money:1}
...
-
Lua實(shí)現(xiàn)搶紅包流程
代碼實(shí)現(xiàn)
do
local userid = 101
-- 查詢用戶是否已經(jīng)搶過紅包
if redis.call("hexists", "redbagBlacklist", userid)~=0 then
return nil
end
-- 從紅包池中獲取紅包
local redbag = redis.call("rpop", "redbagPool")
-- 判斷紅包池是否為空
if redbag==nil then
return nil
end
-- 解析紅包數(shù)據(jù)
local item = cjson.decode(redbag)
-- 將搶過的用戶與紅包添加到黑名單
redis.call("hset", "redbagBlacklist", userid, item["rid"])
-- 將搶紅包結(jié)果存入記錄
item["userid"] = userid
item["create_time"] = os.time()
local redbagUser = cjson.encode(item)
redis.call("lpush", "redbagUser", redbagUser)
return redbagUser
end