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("扣减库存成功!");
    }
相关推荐
BinaryBardC1 小时前
Swift语言的网络编程
开发语言·后端·golang
code_shenbing1 小时前
基于 WPF 平台使用纯 C# 制作流体动画
开发语言·c#·wpf
邓熙榆1 小时前
Haskell语言的正则表达式
开发语言·后端·golang
ac-er88882 小时前
Yii框架中的队列:如何实现异步操作
android·开发语言·php
马船长2 小时前
青少年CTF练习平台 PHP的后门
开发语言·php
hefaxiang3 小时前
【C++】函数重载
开发语言·c++·算法
落幕4 小时前
C语言-构造数据类型
c语言·开发语言
勤又氪猿4 小时前
【问题】Qt c++ 界面 lineEdit、comboBox、tableWidget.... SIGSEGV错误
开发语言·c++·qt
Ciderw4 小时前
Go中的三种锁
开发语言·c++·后端·golang·互斥锁·
查理零世4 小时前
【算法】经典博弈论问题——巴什博弈 python
开发语言·python·算法