Redis分布式锁接口封装实现

说在前面,Redis分布式锁的实现已经烂大街了。 很多人都写过博客,也有写的非常非常好的。 我这里纯属为了自己学习整理一下。 而且现在redis有一个超级牛逼的客户端 Redisson

原理主要是通过redis的nx自增来实现的。

下面就直接上代码

添加依赖

  <dependency>
            <groupId>org.springframework.integration</groupId>
            <artifactId>spring-integration-redis</artifactId>
        </dependency>
          <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

分布式锁的业务无关性完全可以抽成一个接口


public interface DistributedLockTemplate {

    /**
     * 执行方法
     * @param lockId 锁id(对应业务唯一ID)
     * @param timeout 最大等待获取锁时间
     * @param unit 等待时间单位
     * @param callback 回调方法
     * @return
     */
    Object execute(String lockId, Integer timeout, TimeUnit unit, Callback callback);
}

下面就是实现类

private RedisLockRegistry redisLockRegistry; 引用的项目中的依赖 spring-integration-redis

流程如下: 先通过redisLockRegistry获取锁对象Lock, 在通过lock的tryLock方法尝试获取锁,并设置超时时间,如果获取到锁就调用callback中的成功业务逻辑 ,如果无法获取锁就调用callback中的失败获取锁逻辑。 下面会介绍Callback这个函数。 最后如果获取到了锁就释放锁。

@Slf4j
@Component
public class RedisLockTemplate implements DistributedLockTemplate {

    @Autowired
    private RedisLockRegistry redisLockRegistry;

    @Override
    public Object execute(String lockId, Integer timeout, TimeUnit unit, Callback callback) {

        Lock lock = null;
        boolean getLock = false;
        try {
            lock = redisLockRegistry.obtain(lockId);
            getLock = lock.tryLock(timeout, unit);
            if(getLock){
                // 拿到锁
                return callback.onGetLock();
            }else{
                // 未拿到锁
                return callback.onTimeout();
            }
        }catch(InterruptedException ex){
            log.error(ex.getMessage(), ex);
            Thread.currentThread().interrupt();
        }catch (Exception e) {
            log.error(e.getMessage(), e);
        }finally {
            if(getLock) {
                // 释放锁
                lock.unlock();
            }
        }
        return null;
    }
}

下面是Callback接口

public interface Callback {

    /**
     * 成功获取锁后执行方法
     * @return
     * @throws InterruptedException
     */
    Object onGetLock() throws InterruptedException;

    /**
     * 获取锁超时回调
     * @return
     * @throws InterruptedException
     */
    Object onTimeout() throws InterruptedException;
}

分布式锁的使用
将我们定义的模板注入进来就可以使用了。

    @Autowired
    private RedisLockTemplate redisLockTemplate;

    @RequestMapping(value = "/lockAndLimit", method = RequestMethod.GET)
    @ResponseBody
    public Result<Object> test1() {

        redisLockTemplate.execute("订单流水号", 3, TimeUnit.SECONDS, new Callback() {
            @Override
            public Object onGetLock() throws InterruptedException {
                // TODO 获得锁后要做的事
                log.info("生成订单流水号");
                return null;
            }

            @Override
            public Object onTimeout() throws InterruptedException {
                // TODO 未获取到锁(获取锁超时)后要做的事
                log.info("oops 没拿到锁");
                return null;
            }
        });

        return ResultUtil.data(null);
    }

简单分析

这里可以简单分析一下源码, 获取我们通过 lock = redisLockRegistry.obtain(lockId); 获取到的Lock对象是经过包装的。 是RedisLock.class的对象, 我们在调用trylock 和 unlock 都是调用的这个类中的方法。 当然了这个类也是实现 Lock接口的。
在这里插入图片描述

一篇比较不错的介绍分布式锁的文章

重要的事情

交个朋友吧
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值