redis实现简单分布式锁

1.redisTemplate实现简单分布式锁

java 复制代码
 @Autowired
    RedisTemplate redisTemplate;

    /**
     * redis分布式锁演示案例,此处使用redisTemplate
     * @param stockId  此处以扣减库存为例子,stockId代表要扣减库存的商品id,库存数据是提前存在redis的,并和数据库进行同步
     * @return
     */
    public AjaxResult redisLockDemo(String stockId){
        //锁前缀
        final String stock_lock = "stock_lock:";
        // 生成一个随机唯一的值用于辨别锁的使用对象
        String clientId = UUID.randomUUID().toString();
        //此处使用set(k,v,time,unit)来获取锁,确保加锁和设置超时时间是原子操作
        Boolean lock = redisTemplate.opsForValue().setIfAbsent(stock_lock + stockId, clientId, 10, TimeUnit.MILLISECONDS);
        if (!lock){
            //获取锁失败
            return AjaxResult.error("服务器繁忙,请稍后再试!");
        }
        //获取锁成功
        //执行扣减库存
        try {
            int stock = (int) redisTemplate.opsForValue().get(stockId);
            if (stock > 0){
                int realStock = stock - 1;
                // 重新设置库存数据
                redisTemplate.opsForValue().set(stockId, realStock + "");
                // .............其他步骤
                log.info("库存扣减成功{}", stockId);
            } else {
                return AjaxResult.error("商品已经被抢光了!");
            }
        } finally {
           //释放锁
//            if (clientId.equals(stringRedisTemplate.opsForValue().get(stock_lock + stockId))){
//                stringRedisTemplate.delete(stock_lock + stockId);
//            }
            //此处使用lua脚本释放锁,具有原子性
            String script = "local lockKey = KEYS[1]\n" +
                    "local clientId = ARGV[1]\n" +
                    "local currentHolder = redis.call('GET', lockKey)\n" +
                    "if currentHolder == clientId then\n" +
                    "    redis.call('DEL', lockKey)\n" +
                    "    return true\n" +
                    "else\n" +
                    "    return false\n" +
                    "end";
            DefaultRedisScript<Boolean> redisScript = new DefaultRedisScript<>(script, Boolean.class);
            Boolean result = (Boolean) redisTemplate.execute(redisScript, Collections.singletonList(stock_lock + stockId), clientId);

            if (result != null && result) {
               log.info("所释放成功");
            } else {
                log.info("所释放失败");
            }
        }
        return AjaxResult.success("扣减库存成功!");
    }

2.redission实现分布式锁

java 复制代码
    @Autowired
    Redisson redisson; 
/**
     * redis分布式锁演示案例,redisson
     * @param stockId  此处以扣减库存为例子,stockId代表要扣减库存的商品id,库存数据是提前存在redis的,并和数据库进行同步
     * @return
     */
    public AjaxResult redissonLockDemo(String stockId){
        final String lockKey = "stock_lock:";
        RLock lock = redisson.getLock(lockKey);
        lock.lock();
        try {
            //执行扣减库存
            int stock = (int) redisTemplate.opsForValue().get(stockId);
            if (stock > 0){
                int realStock = stock - 1;
                // 重新设置库存数据
                redisTemplate.opsForValue().set(stockId, realStock + "");
                // .............其他步骤
                log.info("库存扣减成功{}", stockId);
            } else {
                return AjaxResult.error("商品已经被抢光了!");
            }
        }finally {
            lock.unlock();
        }
        return AjaxResult.success("扣减库存成功!");
    }
相关推荐
辛苦才能3 分钟前
C++多态原理:虚函数表的内存布局与动态绑定的汇编真相
开发语言·c++
铲灰6 分钟前
做个总结而已
开发语言
IvanCodes14 分钟前
Python 文件操作(十二):文件与目录的读写
开发语言·python
神仙别闹9 小时前
基于 C++ 实现(控制台)学生成绩管理系统
开发语言·c++
伞伞悦读9 小时前
【第36期】Python 目录与路径详解:pathlib、文件遍历、创建、复制、移动和删除风险
开发语言·python
2601_9669496512 小时前
只拿到股票代码还不够:量化程序到底还需要哪些标的信息?——从数据建模开始理解股票元数据
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
m0_7345717612 小时前
深入理解5g <十八>传输块tbsize的计算
开发语言·5g
RAN114267600814 小时前
1.3第一个程序的介绍
开发语言·qt
blue_ice .14 小时前
Verilog DDS 数字信号发生器:DAC 输出模拟波形与 ADC 回采观测
开发语言·单片机·嵌入式硬件·fpga开发
远翔调光芯片^1382879887215 小时前
ECP5702能芯科技PD取电芯片在市场上的优势有哪些?
开发语言·人工智能·单片机·嵌入式硬件·智能家居