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 分钟前
利用D3.js实现数据可视化的简单示例
开发语言·javascript·信息可视化
程序猿阿伟4 分钟前
《C++ 实现区块链:区块时间戳的存储与验证机制解析》
开发语言·c++·区块链
傻啦嘿哟22 分钟前
如何使用 Python 开发一个简单的文本数据转换为 Excel 工具
开发语言·python·excel
大数据编程之光26 分钟前
Flink Standalone集群模式安装部署全攻略
java·大数据·开发语言·面试·flink
初九之潜龙勿用27 分钟前
C#校验画布签名图片是否为空白
开发语言·ui·c#·.net
Dola_Pan44 分钟前
C语言:数组转换指针的时机
c语言·开发语言·算法
ExiFengs44 分钟前
实际项目Java1.8流处理, Optional常见用法
java·开发语言·spring
paj1234567891 小时前
JDK1.8新增特性
java·开发语言
IT古董1 小时前
【人工智能】Python在机器学习与人工智能中的应用
开发语言·人工智能·python·机器学习
繁依Fanyi1 小时前
简易安卓句分器实现
java·服务器·开发语言·算法·eclipse