Redis实现分布式锁的正确姿势

加锁姿势

1、setNotExist命令了解;
2、为了防止死锁,需要设置超时时间;
3、设置锁:key-value时需要同时指定超时时间,避免服务突然宕机产生死锁问题;
4、加锁成功设置延迟检查任务,比如超时时间的一半执行锁状态检查,若资源依旧处于处理占有中,则需要对锁做‘续命’操作,防止超时自动释放锁导致进程间并发安全问题,并且需要设置续命次数上限,必要时打印关键日志警告;
5、设置锁时需要将value设置为一个能够区分各个客户端的id(比如uuid),用于释放锁时判断,避免误删;(意思就是a节点设置的锁,只能是a节点来删除(除非达到续命上限,超时自动释放));

    private static final String LOCK_SUCCESS = "OK";
    // nxxx NX|XX, NX -- Only set the key if it does not already exist. XX -- Only set the key if it already exist.
    private static final String SET_IF_NOT_EXIST = "NX";
    // expire time units: EX = seconds; PX = milliseconds
    private static final String SET_WITH_EXPIRE_TIME = "PX";
    public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) {
        // nxxx NX|XX, NX -- Only set the key if it does not already exist. XX
        // expire time units: EX = seconds; PX = milliseconds
        String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
        if (LOCK_SUCCESS.equals(result)) {
            return true;
        }
        return false;
    }

解锁姿势

1、解锁需要保证命令的原子性,使用脚本进行封装;谁加的锁谁来解

        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));
        // 根据result做判断
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。