分布式锁一般有三种实现方式:1. 数据库乐观锁;2. 基于Redis的分布式锁;3. 基于ZooKeeper的分布式锁
本文主要介绍了Java代码如何正确实现Redis分布式锁,对于加锁和解锁也分别给出了几个比较经典的错误示例
分布式锁可靠性条件
1.互斥性、在任意时刻,只有一个客户端能持有锁。
2.不会发生死锁、即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁。
3.具有容错性、只要大部分的Redis节点正常运行,客户端就可以加锁和解锁。
4.解铃还须系铃人、加锁和解锁必须是同一个客户端,客户端自己不能把别人加的锁给解了。
加锁
正确的加锁方式
private static final String OK = "OK";
/**
* 尝试获取分布式锁
*
* @param jedis Redis客户端
* @param key 锁key
* @param requestId 值(请求标识)
* @param expireTime 超期时间
* @return 是否获取成功
*/
public static boolean lock(Jedis jedis, String key, String requestId, int expireTime) {
String result = jedis.set(key, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
if (OK.equals(result)) {
return true;
}
return false;
}
加锁就一行代码(防并发)
jedis.set(String key, String value, String nxxx, String expx, int time)
该set()方法一共有五个形参:
参数说明
key :唯一key值,可以使用key来当锁
requestId :缓存的value 值,用于表示加锁的客户端。解锁时需要判断加锁与解锁是否是相同客户端
nxxx :常量值NX ,含义是SET IF NOT EXIST,
即当key不存在时,进行set操作;若key已经存在,则不做任何操作
expx