• Redisson解决redis分布式锁过期业务没执行完问题


    Redisson
    Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。

    Redisson不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式服务。其中包括(BitSet, Set, Multimap, SortedSet, Map, List, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, AtomicLong, CountDownLatch, Publish / Subscribe, Bloom filter, Remote service, Spring cache, Executor service, Live Object service, Scheduler service), Redisson提供了使用Redis的最简单和最便捷的方法。

    Redisson的宗旨是促进使用者对Redis的关注分离(Separation of Concern),从而让使用者能够将精力更集中地放在处理业务逻辑上。

    lua代码实现
    通过封装在lua脚本中发送给redis,保证这段复杂业务逻辑执行的原子性。

    加锁
    if (redis.call('exists', KEYS[1]) == 0) then
    redis.call('hset', KEYS[1], ARGV[2], 1);
    redis.call('pexpire', KEYS[1], ARGV[1]);
    return nil;
    end;
    if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then
    redis.call('hincrby', KEYS[1], ARGV[2], 1);
    redis.call('pexpire', KEYS[1], ARGV[1]);
    return nil;
    end;
    return redis.call('pttl', KEYS[1]);
    释放锁
    if (redis.call('exists', KEYS[1]) == 0) then
    redis.call('publish', KEYS[2], ARGV[1]);
    return 1;
    end;
    if (redis.call('hexists', KEYS[1], ARGV[3]) == 0) then
    return nil;
    end;
    local counter = redis.call('hincrby', KEYS[1], ARGV[3], -1);
    if (counter > 0) then
    redis.call('pexpire', KEYS[1], ARGV[2]);
    return 0;
    else redis.call('del', KEYS[1]);
    redis.call('publish', KEYS[2], ARGV[1]);
    return 1;
    end;
    return nil;
    Redisson实现分布式锁
    可重入锁
    RLock lock = redisson.getLock("lock");
    lock.lock();

    lock.unlock()

    // 加锁以后10秒钟自动解锁
    // 无需调用unlock方法手动解锁
    lock.lock(10, TimeUnit.SECONDS);

    // 尝试加锁,最多等待100秒,上锁以后10秒自动解锁
    boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
    ...
    lock.unlock();
    公平锁
    RLock fairLock = redisson.getFairLock("anyLock");
    // 最常见的使用方法
    fairLock.lock();

    // 10秒钟以后自动解锁
    // 无需调用unlock方法手动解锁
    fairLock.lock(10, TimeUnit.SECONDS);

    // 尝试加锁,最多等待100秒,上锁以后10秒自动解锁
    boolean res = fairLock.tryLock(100, 10, TimeUnit.SECONDS);
    ...
    fairLock.unlock();
    watch dog自动延期机制
    Redisson中客户端一旦加锁成功,就会启动一个watch dog看门狗。watch dog是一个后台线程,会每隔10秒检查一下,如果客户端还持有锁key,那么就会不断的延长锁key的生存时间。

    如果负责存储这个分布式锁的Redission节点宕机后,而且这个锁正好处于锁住的状态时,这个锁会出现锁死的状态,为了避免这种情况的发生,Redisson提供了一个监控锁的看门狗,它的作用是在Redisson实例被关闭前,不断的延长锁的有效期。默认情况下,看门狗的续期时间是30s,也可以通过修改Config.lockWatchdogTimeout来另行指定。

    另外Redisson 还提供了可以指定leaseTime参数的加锁方法来指定加锁的时间。超过这个时间后锁便自动解开了,不会延长锁的有效期。

    缺点
    对某个redis master实例,写入了myLock这种锁key的value,此时会异步复制给对应的master slave实例。但是这个过程中一旦发生redis master宕机,主备切换,redis slave变为了redis master。就会导致客户端2来尝试加锁的时候,在新的redis master上完成了加锁,而客户端1也以为自己成功加了锁。

    此时就会导致多个客户端对一个分布式锁完成了加锁。这时系统在业务上一定会出现问题,导致脏数据的产生。所以这个就是redis cluster,或者是redis master-slave架构的主从异步复制导致的redis分布式锁的最大缺陷:在redis master实例宕机的时候,可能导致多个客户端同时完成加锁。

  • 相关阅读:
    openstack首页默认跳转
    centos7.3挂在移动硬盘(亲测)
    管理openstack多region介绍与实践
    一款功能强悍的web磁盘管理工具 (A powerful web disk management tools)
    文件及目录的归属关系
    Linux 权限基础说明
    umask默认权限分配
    linux删除、读取文件原理
    linux 文件类型
    LINUX 目录结构
  • 原文地址:https://www.cnblogs.com/fan-1994716/p/14994812.html
Copyright © 2020-2023  润新知