Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

解决可能存在少买问题 #44

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/main/java/ltd/newbee/mall/redis/RedisCache.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,19 @@ public Long luaDecrement(final String key) {
return execute.longValue();
}

public void luaIncrement(final String key) {
RedisScript<Long> redisScript = new DefaultRedisScript<>(buildLuaIncrScript(), Long.class);
Number execute = (Number) redisTemplate.execute(redisScript, Collections.singletonList(key));
}

private String buildLuaIncrScript() {
return """
local c
c = redis.call('incr',KEYS[1])
return c;""";
}


/**
* lua原子自减脚本
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,6 @@ public SeckillSuccessVO executeSeckill(Long seckillId, Long userId) {
if (redisCache.containsCacheSet(Constants.SECKILL_SUCCESS_USER_ID + seckillId, userId)) {
throw new NewBeeMallException("您已经购买过秒杀商品,请勿重复购买");
}
// 更新秒杀商品虚拟库存
Long stock = redisCache.luaDecrement(Constants.SECKILL_GOODS_STOCK_KEY + seckillId);
if (stock < 0) {
throw new NewBeeMallException("秒杀商品已售空");
}
NewBeeMallSeckill newBeeMallSeckill = redisCache.getCacheObject(Constants.SECKILL_KEY + seckillId);
if (newBeeMallSeckill == null) {
newBeeMallSeckill = newBeeMallSeckillMapper.selectByPrimaryKey(seckillId);
Expand All @@ -139,7 +134,11 @@ public SeckillSuccessVO executeSeckill(Long seckillId, Long userId) {
} else if (nowTime > endTime) {
throw new NewBeeMallException("秒杀已结束");
}

// 更新秒杀商品虚拟库存
Long stock = redisCache.luaDecrement(Constants.SECKILL_GOODS_STOCK_KEY + seckillId);
if (stock < 0) {
throw new NewBeeMallException("秒杀商品已售空");
}
Date killTime = new Date();
Map<String, Object> map = new HashMap<>(8);
map.put("seckillId", seckillId);
Expand All @@ -150,12 +149,16 @@ public SeckillSuccessVO executeSeckill(Long seckillId, Long userId) {
try {
newBeeMallSeckillMapper.killByProcedure(map);
} catch (Exception e) {
//恢复redis扣减
redisCache.luaIncrement(Constants.SECKILL_GOODS_STOCK_KEY + seckillId);
throw new NewBeeMallException(e.getMessage());
}
// 获取result -2sql执行失败 -1未插入数据 0未更新数据 1sql执行成功
map.get("result");
int result = MapUtils.getInteger(map, "result", -2);
if (result != 1) {
//恢复redis扣减
redisCache.luaIncrement(Constants.SECKILL_GOODS_STOCK_KEY + seckillId);
throw new NewBeeMallException("很遗憾!未抢购到秒杀商品");
}
// 记录购买过的用户
Expand Down