简介
做秒杀的商品数量一般计较少
该方案使用set存储 一定库存
每个用户抢购时,从redis申请序号, 取到了则创建订单。
可与前端缓存方案 限流 熔断一起使用
测试
1
2
3
4
5
6
7
8
|
cat > test.lua <<EOF
local t1 = redis.call('scard', "aaa")
local t2 = tonumber(t1)
local t3 = redis.call('exists', "aaa")
return t1;
EOF
redis-cli --ldb --eval test.lua a , b
|
方式a
在抢购开始前,由定时任务,或其他方式,在redis中添加商品
用户抢到购买资格后, 由另外的线程去为该用户生产订单
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
cat > sbuy.lua <<EOF
local apples = string.format("sapples-{%s}", KEYS[1]) -- 某商品库存
local holdNumUser = string.format("sbuyed-{%s}", KEYS[1]) -- 某商品已购者set集合
local buyId = ARGV[1] -- 购买人id
if redis.call('sismember', holdNumUser, buyId) > 0
then return -2; -- 已抢购到商品
elseif redis.call('scard', apples) < 1
then return -1; -- 商品库存不足,秒杀失败
end
-- 取出一个商品,同时将购买人
local productSerialNo = redis.call("spop", apples);
redis.call('sadd', holdNumUser, buyId);
return productSerialNo;
EOF
##-- 商品id, 购买人id
PRODUCTID=P666
BuyId=u001
##-- 添加商品--由java代码调用添加带秒杀商品
redis-cli sadd sapples-{$PRODUCTID} 1 2 3
redis-cli scard sbuyed-{$PRODUCTID}
redis-cli smembers sbuyed-{$PRODUCTID}
redis-cli exists sbuyed-{$PRODUCTID}
redis-cli EVAL "$(cat sbuy.lua)" 1 $PRODUCTID $BuyId
redis-cli --ldb --eval sbuy.lua $PRODUCTID , $BuyId
|
方式b
商品购支付成功后,才认为秒杀结束
当用户获得抢购资格时, 将商品序号加入带支付set中
库存没有了,可以提示用户还有未付款订单,可以再等等
当该商品支付成功后, 从待支付中移除该序号,即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
cat > sbuy02.lua <<EOF
local apples = string.format("sapples-{%s}", KEYS[1]) -- 某商品库存
local holdNumUser = string.format("sbuyed-{%s}", KEYS[1]) -- 某商品已购者set集合
local waitpay = string.format("switpay-{%s}", KEYS[1]) -- 某商品待支付序号set集合
local buyId = ARGV[1] -- 购买人id
if redis.call('sismember', holdNumUser, buyId) > 0
then return -2; -- 已抢购到商品
elseif redis.call('scard', apples) < 1
then -- 待支付序号数量 > 0 则还有未付款商品, 否则秒杀结束
if redis.call('scard', waitpay) > 0 then return -3; end
return -1; -- 商品库存不足,秒杀失败
end
-- 取出一个商品,同时将购买人
local productSerialNo = redis.call("spop", apples);
redis.call('sadd', holdNumUser, buyId);
redis.call('sadd', waitpay, buyId);
return productSerialNo;
EOF
|
当某笔订单成功支付,则从redis中移除该 waitpay 的序号
当订单被取消,则重新加入 apples 中
方式c
redis以计数器的方式 为用户提供抢购服务
文章作者
duansheli
上次更新
2019-12-25
(325c7b3)