抢购活动使用redis加锁,造成商品卖不完的问题?

发布于 2022-09-12 03:56:04 字数 1047 浏览 22 评论 0

public SeckillActivityRequestVO seckillHandle(SeckillActivityRequestVO request) {
SeckillActivityRequestVO response;
    String key = "key:" + request.getSeckillId;
    try {
        Boolean lockFlag = redisTemplate.opsForValue().setIfAbsent(key, "val", 10, TimeUnit.SECONDS);
        if (lockFlag) {
            // HTTP请求用户服务进行用户相关的校验
            // 用户活动校验
            
            // 库存校验
            Object stock = redisTemplate.opsForHash().get(key+":info", "stock");
            assert stock != null;
            if (Integer.parseInt(stock.toString()) <= 0) {
                // 业务异常
            } else {
                redisTemplate.opsForHash().increment(key+":info", "stock", -1);
                // 生成订单
                // 发布订单创建成功事件
                // 构建响应VO
            }
        }
    } finally {
        // 释放锁
        stringRedisTemplate.delete("key");
        // 构建响应VO
    }
    return response;
}

很显然,上面的代码,如果是在高并发下,大量的请求其实是获取不到锁,返回的response都是null,这会造成商品卖不完的现象。所以我觉得抢购获取不应该使用锁。
不知道大家有没有什么看法呢??

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

最初的梦 2022-09-19 03:56:04

看了你的操作,为什么要锁呢?

直接 incrby -1 如果的到的值大于等于0 就说明当前请求拿到了库存,继续往下发送订单事件.如果得到的值小于0 就说明当前请求没有拿到库存,返回抢购失败就可以了啊.

直接利用 incrby 的原子性来进行库存的操作就可以了啊.

不即不离 2022-09-19 03:56:04

不加锁是不可能的,超卖是比卖不完更严重的问题,没有锁就没法保证数量的一致性,就没法保证不超卖,卖不完的情况只能是在保证不超卖的情况下优化,比如减小锁粒度等等

楼上说的那个,基于incrby的原子性,明明这个命令是三个操作,先get,再加法,再写回,为什么就是原子操作了?还不是redis替你保证了并发安全。所以并非是没有加锁,只是redis替你做了,你就不用再自己实现。但这只是你的库存存到了redis才能这么做,如果存在mysql呢

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文