redis分布式锁
作者:互联网
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便执行完代码
标签:return,String,解锁,redis,jedis,requestId,lockKey,分布式 来源: https://www.cnblogs.com/enhance/p/10988536.html