- 数据库
- redis
- zookeeper
znode四种类型:
- 持久节点 (PERSISTENT)
- 持久顺序节点(PERSISTENT_SEQUENTIAL)
- 临时节点(EPHEMERAL)
- 临时顺序节点(EPHEMERAL_SEQUENTIAL)
zookeeper
创建一个持久节点,在这个节点下创建临时顺序节点,如果顺序是第一个,就获取锁;
如果不是第一个,就监听前面一个节点的状态
redis
加锁:
String threadId = Thread.currentThread().getId()
set(key,threadId ,30,NX)
解锁:
if(threadId .equals(redisClient.get(key))){
del(key)}
释放锁:判断和释放锁是两个独立操作,不是原子性,可以用lua脚本解决。
public class JedisDtLock extends JedisBase implements DtLock {
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";
private static final int DEFAULT_OWN_TIMEOUT = 30;
/**
* 锁失效超时时间,单位:毫秒
*/
private int ownTimeoutSecond = DEFAULT_OWN_TIMEOUT;
public JedisDtLock(String name) {
setKeyName(name + ":DtLock");
}
@Override
public String tryLock() {
String kId = UuidUtil.uuid();
String result = getJedis().set(getKeyName(), kId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME,
ownTimeoutSecond * 1000);
return LOCK_SUCCESS.equals(result) ? kId : null;
}
@Override
public void unLock(String kId) {
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return "
+ "0 end";
getJedis().eval(script, Collections.singletonList(getKeyName()), Collections.singletonList(kId));
}
public int getOwnTimeoutSecond() {
return ownTimeoutSecond;
}
public void setOwnTimeoutSecond(int ownTimeoutSecond) {
this.ownTimeoutSecond = ownTimeoutSecond;
}
}