分布式锁学习

  • 数据库
  • redis
  • zookeeper

znode四种类型:

  • 持久节点 (PERSISTENT)
  • 持久顺序节点(PERSISTENT_SEQUENTIAL)
  • 临时节点(EPHEMERAL)
  • 临时顺序节点(EPHEMERAL_SEQUENTIAL)

zookeeper

创建一个持久节点,在这个节点下创建临时顺序节点,如果顺序是第一个,就获取锁;
如果不是第一个,就监听前面一个节点的状态


zk获取锁过程.png

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;
    }
}

from:https://gitee.com/xuan698400/distributed-tool

你可能感兴趣的:(分布式锁学习)