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("扣减库存成功!");
    }
相关推荐
又蓝5 分钟前
使用 Python 操作 Excel 表格
开发语言·python·excel
余~~1853816280017 分钟前
稳定的碰一碰发视频、碰一碰矩阵源码技术开发,支持OEM
开发语言·人工智能·python·音视频
Am心若依旧4091 小时前
[c++11(二)]Lambda表达式和Function包装器及bind函数
开发语言·c++
明月看潮生1 小时前
青少年编程与数学 02-004 Go语言Web编程 20课题、单元测试
开发语言·青少年编程·单元测试·编程与数学·goweb
大G哥1 小时前
java提高正则处理效率
java·开发语言
VBA63371 小时前
VBA技术资料MF243:利用第三方软件复制PDF数据到EXCEL
开发语言
轩辰~1 小时前
网络协议入门
linux·服务器·开发语言·网络·arm开发·c++·网络协议
小_太_阳1 小时前
Scala_【1】概述
开发语言·后端·scala·intellij-idea
向宇it1 小时前
【从零开始入门unity游戏开发之——unity篇02】unity6基础入门——软件下载安装、Unity Hub配置、安装unity编辑器、许可证管理
开发语言·unity·c#·编辑器·游戏引擎
古希腊掌管学习的神2 小时前
[LeetCode-Python版]相向双指针——611. 有效三角形的个数
开发语言·python·leetcode