redis分布式锁(redis实现及redisson实现)

        今天做任务用到了redis的分布式锁,分享一下,不足之处还请大佬指正。

方法一

        使用redis,我们想要自己实现分布式锁,首先要防止死锁、占用时间过长等问题,以下是分布式锁的流程,分为两个线程,左半边为主线程,右半边为守护线程。

redis分布式锁(redis实现及redisson实现)_第1张图片

        由于我并没有用这种方法做,只是设计了一下,就不战列具体代码,只说思路。

        首先我们要封装三个方法,降低耦合性,设置参数的时候要考虑灵活性,这样其他的代码也可以使用。

        这里的添加锁和释放锁时的操作代码尽量使用lua脚本语言编写,来保证操作的原子性,防止执行过程中服务器宕机。

        第一个方法tryGetDistributedLock(),尝试获取分布式锁。参数已经列出来了,key值就是你要锁的对象的key值。request建议使用uuid生成,存活时间就是到了多久之后,不管你的程序有没有执行结束,我都要把这个锁释放。返回boolean值,添加成功返回true,失败返回false,很多个线程同时来操作这个方法,但是只有第一个线程能成功,添加锁得到true,其余的线程都会得到false。

/**
     * 尝试获取分布式锁
     *
     * @param jedis Redis客户端
     * @param lockKey  key值
     * @param requestId  请求标识
     * @param expireTime  存活时间
     * @return  是否获取成功
     */
    public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime){}

        第二个方法releaseDistributedLock(),释放分布式锁。key值就是你要锁的对象得key值。request使用添加锁时候生成的uuid,用来防止其他用户来释放你的锁,释放时,必须lockKey和requestId都和添加锁时一致才可以释放。

/**
     * 释放分布式锁
     *
     * @param jedis  Redis客户端
     * @param lockKey  key值
     * @param requestId  请求标识
     * @return  是否释放成功
     */
    public static boolean releaseDistributedLock(Jedis jedis,String lockKey,String requestId){}

         第三个方法启动守护线程。启动另一个线程,这里关于时间的计算比较乱,容易晕,请你跟好我的思路。

        lockKey和requestId就不说了,和前面一样,这个方法里面要设置一个大的循环,每三秒循环一次,循环体内检测还有多久的剩余时长,也就是(当前系统时间 减去 添加锁时系统时间)如果这个时间小于存活时长的1/3,那我们就要给他添加时长,每次添加everyAddTime,记录添加的次数,添加次数达到maxIncreaseNumber 后不在添加,超时后释放锁。

        此方法里可能会涉及到时间的递归赋值,尽量不要使用lambda表达式来启动线程。

    /**
     * 启动守护线程
     *
     * @param jedis  Redis客户端
     * @param lockKey  key值
     * @param requestId  请求标识
     * @param addLockSystemTime 添加锁时系统时间
     * @param maxIncreaseNumber  最大增加次数
     * @param everyAddTime  每次增加时长
     * @param expireTime  存活时长
     */
    public static void startDaemonThread(Jedis jedis,String lockKey,
                                String requestId,Long addLockSystemTime,int maxIncreaseNumber,
                                int everyAddTime,int expireTime){}

方法二

        使用redisson,这个是redis官方推荐的一个工具,很牛,关于分布式锁的这里面封装得很完整

首先从配置文件中获取redis连接信息,创建Redisson实例对象

redis分布式锁(redis实现及redisson实现)_第2张图片redis分布式锁(redis实现及redisson实现)_第3张图片

         然后在你的代码上方获取锁

//获取锁
RLock rLock= RedisHelper.getRedissonClient().getLock(“你需要锁的对象key值”);

        尝试添加锁,tryLock()方法添加成功返回true,失败返回false,很多个线程同时来操作这个方法,但是只有第一个人能成功,添加锁得到true,其余的线程都会得到false。

        第一个参数表示的是最多可以延长多久,这个延长时间你可以理解为续命,每次它检测到线程要死了,就马上给他续命,最多只能续到300秒(由第一个参数定义,我定义的是300秒),300秒之后不管程序是否执行完毕,都释放锁。第二个参数是他的存活时间,很多人会担心他的死锁问题,如果服务器突然宕机怎么办?第二个参数就是为了防止这种情况。如果该服务器宕机,从添加锁开始算30秒,如果没有人给它续命的话,他会自己释放锁。第三个参数就是前两个参数的单位。

try {
    //tryLock(最长等待时间,存活时间,单位)
    if (!rLock.tryLock(300,30, TimeUnit.SECONDS)){
        logger.error("该电签正在进行中");
        throw new MessageException("该电签正在进行中");
    }catch(Exection e){
    }finally{
        //释放锁
        rLock.unlock();
    }

你可能感兴趣的:(笔记,redis,分布式,缓存)