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("扣减库存成功!");
    }
相关推荐
csbysj20204 分钟前
Web 标准
开发语言
老姚---老姚20 分钟前
在windows下编译go语言编写的dll库
开发语言·windows·golang
diediedei31 分钟前
模板编译期类型检查
开发语言·c++·算法
穿过锁扣的风40 分钟前
零基础入门 Python 爬虫:从基础到实战,爬取虎扑 / 豆瓣 / 图片全掌握
开发语言·爬虫·python
一切尽在,你来1 小时前
C++多线程教程-1.2.1 C++11/14/17 并发特性迭代
开发语言·c++
80530单词突击赢1 小时前
C++入门指南:从零到精通
开发语言·c++
小突突突1 小时前
浅谈Java中的反射
java·开发语言
csbysj20201 小时前
JSP 发送邮件教程
开发语言
Tansmjs2 小时前
C++编译期数据结构
开发语言·c++·算法
金枪不摆鳍2 小时前
算法-字典树
开发语言·算法