首页 > 其他 > 详细

redis分布式锁

时间:2019-06-07 17:39:26      阅读:312      评论:0      收藏:0      [点我收藏+]

 

1、Redis分布式锁流程图(二个要点:①超时解锁 ②获得锁的线程唯一标识,用以谁的锁谁来解锁)

  技术分享图片

2、Redis分布式锁算法:

  ①加锁

    a:锁的唯一标识(设置随机值作为锁的持有人,只有锁的持有人才可以解锁)

    b:锁的超时时间

      加锁指令:jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime)

      lockKey:key值

      requestID:value值,即锁的唯一标识,只有该requestId才可以解锁对应锁

      set_if_not_exist:当key不存在时进行set操作,如果key存在则不做任何操作

      set_with_expire_time:过期时间key

      expireTime:具体过期时间值(一般是通过压测得到一个经验值)

   ②解锁

    a:检查是否持有锁

    b:持有锁条件下删除锁

    采用Lua脚本进行删锁操作

    技术分享图片

 

3、redis代码:

3.1redis加锁代码

   技术分享图片
public class RedisTool {

    private static final String LOCK_SUCCESS = "OK";
    private static final String SET_IF_NOT_EXIST = "NX";
    private static final String SET_WITH_EXPIRE_TIME = "PX";

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

        String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);

        if (LOCK_SUCCESS.equals(result)) {
            return true;
        }
        return false;

    }

}
View Code

  上述代码执行有两个结果:①锁不存在,进行加锁操作   ②存在锁,不做任何操作

  代码中满足三个条件:①requestID唯一锁持有人标识 ,满足谁的锁谁去解锁

            ②expireTime 设置超时时间,如果超时自动解锁

            ③nx 保证key存在则不进行任何操作

 

3.2redis解锁代码  

技术分享图片
public class RedisTool {

    private static final Long RELEASE_SUCCESS = 1L;

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

        String script = "if redis.call(‘get‘, KEYS[1]) == ARGV[1] then return redis.call(‘del‘, KEYS[1]) else return 0 end";
        Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));

        if (RELEASE_SUCCESS.equals(result)) {
            return true;
        }
        return false;

    }

}
View Code

  我们将Lua代码传到jedis.eval()方法里,并使参数KEYS[1]赋值为lockKey,ARGV[1]赋值为requestId。eval()方法是将Lua代码交给Redis服务端执行。

  Lua脚本功能:获取key对应的value,然后和requestID对比是否一样,如果一样则解锁,返回true,如果不相等则返回false

 

 

4、主节点在同步锁到子节点前挂掉处理方案:redLock

                          技术分享图片

 

                   技术分享图片

另外,如果客户端A在master1、2、3获取到锁后,master1宕机,此时客户端B又过来请求锁,在master1、4、5获得锁,这种情况下A、B均获得锁了,解决方案是:master1宕机后不会立马重启,而是延迟重启,在延迟重启的时间段内,保证客户端A便执行完代码

 

redis分布式锁

原文:https://www.cnblogs.com/enhance/p/10988536.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!