分布式-7-分布式锁

2019-10-02  本文已影响0人  宠辱不惊的咸鱼

good article

需求

数据库方式

缓存(redis,memcached,Tair)

Tair

// 加锁
public boolean trylock(String key) {
    ResultCode code = ldbTairManager.put(NAMESPACE, key, "This is a Lock.", 2, 0);
    if (ResultCode.SUCCESS.equals(code))
        return true;
    else
        return false;
}
//解锁
public boolean unlock(String key) {
    ldbTairManager.invalid(NAMESPACE, key);
}

redis正确姿势

// set key value [ex seconds]|[px milliseconds] [nx|xx]
public class RedisTool {
    // NX:不存在创建,返回OK,否则返回null
    // XX:存在返回OK,否则返回null
    // EX:秒,PX:毫秒;只能设置一个
 
    public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) {
        String result = jedis.set(lockKey, requestId, "NX", "PX", expireTime);
        if ("OK".equals(result)) {
            return true;
        }
        return false;
    }
}
public class RedisTool {
 
    private static final Long RELEASE_SUCCESS = 1L;
 
    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;
    }
}

redis错误加锁姿势1

public static void wrongGetLock1(Jedis jedis, String lockKey, String requestId, int expireTime) {
    Long result = jedis.setnx(lockKey, requestId);
    if (result == 1) {
        jedis.expire(lockKey, expireTime);
    }
 
}

redis错误加锁姿势2

public static boolean wrongGetLock2(Jedis jedis, String lockKey, int expireTime) {
    long expires = System.currentTimeMillis() + expireTime;
    String expiresStr = String.valueOf(expires);
    
    // 获得锁
    if (jedis.setnx(lockKey, expiresStr) == 1) {
        return true;
    }
 
    // 锁已存在,获取锁过期时间
    String currentValueStr = jedis.get(lockKey);
    if (currentValueStr != null && Long.parseLong(currentValueStr) < System.currentTimeMillis()) {
        // 锁已过期,获取上一个锁的过期时间,并设置现在锁的过期时间
        String oldValueStr = jedis.getSet(lockKey, expiresStr);
        if (oldValueStr != null && oldValueStr.equals(currentValueStr)) {
            // 考虑多线程并发的情况,只有一个线程的设置值和当前值相同,它才有权利加锁
            return true;
        }
    }
 
    // 其他情况,一律返回加锁失败
    return false;
 
}

redis错误解锁姿势1

public static void wrongReleaseLock1(Jedis jedis, String lockKey) {
    jedis.del(lockKey);
}

redis错误解锁姿势2

public static void wrongReleaseLock2(Jedis jedis, String lockKey, String requestId) {
    if (requestId.equals(jedis.get(lockKey))) {
        jedis.del(lockKey);
    }
}

ZK

上一篇 下一篇

猜你喜欢

热点阅读