Redis秒杀案例(基于springboot)

(Redis秒杀案例(基于springboot))

以下代码块虽然解决了,超卖问题(同时有多个进程来,会导致数据不同步),但是在分布式环境下,并发量高的话仍然又超卖问题。

@RestController
public class indexController {
    @Autowired
    private Redisson redisson;
    @Autowired
    private  StringRedisTemplate stringRedisTemplate;

    @RequestMapping("/deduct_stock")
    public String deductStock(){
       synchronized(this){
           int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("stock"));
           if(stock > 0){
               int realStock = stock - 1;
               stringRedisTemplate.opsForValue().set("stock",realStock + " ");
               System.out.println("扣减成功,剩余库存:"+realStock);
           }else {
               System.out.println("扣减失败,库存不足");
           }
       }
        return "end";
    }
}

解决高并发场景下的超卖问题,除了解决不了宕机问题,还有就是在高并发场景下导致进程会错误删除其他进程的锁,导致锁的失效,也会引起超卖问题

@RestController
public class indexController {
    @Autowired
    private Redisson redisson;
    @Autowired
    private  StringRedisTemplate stringRedisTemplate;

    @RequestMapping("/deduct_stock")
    public String deductStock(){

        String lockKey = "lockKey";//简单的不完善的分布式状态锁
        try {
            Boolean result = stringRedisTemplate.opsForValue().setIfAbsent("lockKey", "zhujian");//jedis.setnx(key,value)
            if(!result){
                return "error_code";//前端根据错误状态码,做出友好提示
            }
            int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("stock"));
            if(stock > 0){
                int realStock = stock - 1;
                stringRedisTemplate.opsForValue().set("stock",realStock + " ");
                System.out.println("扣减成功,剩余库存:"+realStock);
            }else {
                System.out.println("扣减失败,库存不足");
            }
        } finally {
            stringRedisTemplate.delete(lockKey);
        }
        
        return "end";
    }
}

解决办法

@RestController
public class indexController {
    @Autowired
    private Redisson redisson;
    @Autowired
    private  StringRedisTemplate stringRedisTemplate;

    @RequestMapping("/deduct_stock")
    public String deductStock(){

        String lockKey = "lockKey";//简单的不完善的分布式状态锁
        String s = UUID.randomUUID().toString();//为防止进程错误删除其他进程的锁,给进程的做提添加一个uuid标志
        try {
            Boolean result = stringRedisTemplate.opsForValue().setIfAbsent("lockKey", "zhujian",10, TimeUnit.SECONDS);//jedis.setnx(key,value)
            if(!result){
                return "error_code";//前端根据错误状态码,做出友好提示
            }
            int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("stock"));
            if(stock > 0){
                int realStock = stock - 1;
                stringRedisTemplate.opsForValue().set("stock",realStock + " ");
                System.out.println("扣减成功,剩余库存:"+realStock);
            }else {
                System.out.println("扣减失败,库存不足");
            }
        } finally {
            stringRedisTemplate.delete(lockKey);
        }
        return "end";
    }
}

上面虽然可以防止进程错误删除其他进程的锁,但是当锁被释放掉时,在高并发场景下难免会导致uuid的重复,导致多个进程仍会错删其他进程的锁,仍会引起超卖问题。

解决办法:在后台加个分线程,对分分线程加个定时任务,判断主线程是否还存在当时添加的锁,如果存在就给他延长当初加锁的时间。(代码实现较难),目前市场有很多开源框架,例如redisson,具体逻辑如下图:

在这里插入图片描述

redisson实现上述逻辑(内部有看门狗机制),如下代码

@RestController
public class indexController {
    @Autowired
    private Redisson redisson;
    @Autowired
    private  StringRedisTemplate stringRedisTemplate;

    @RequestMapping("/deduct_stock")
    public String deductStock(){

        String lockKey = "lockKey";//简单的不完善的分布式状态锁
        RLock reLock = redisson.getLock(lockKey);
        try {
            reLock.lock();//相当于setIfAbsent("lockKey", "zhujian",10, TimeUnit.SECONDS);
            int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("stock"));
            if(stock > 0){
                int realStock = stock - 1;
                stringRedisTemplate.opsForValue().set("stock",realStock + " ");
                System.out.println("扣减成功,剩余库存:"+realStock);
            }else {
                System.out.println("扣减失败,库存不足");
            }
        } finally {
            reLock.unlock();
        }
        return "end";
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芝士汉堡 ིྀིྀ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值