Redis 分布式锁之红锁 Redisson java实现

算法思想

  1. 获得当前时间(ms)

  2. 首先设置一个锁有效时间valid_time,也就是超过这个时间后锁自动释放,使用相同的key和value对所有redis实例进行设置,每次链接redis实例时设置一个小于valid_time的超时时间,比如valid_time时10s,那超时时间可以设置成50ms,如果这个实例不行,那么换下一个设置

  3. 计算获取锁总共占用的时间,再加上时钟偏移,如果这个总时间小于valid_time,并且成功设置锁的实例数>= N/2 + 1,那么加锁成功

直白点说,就是采用多个个独立的redis节点,同时setnx,如果多数节点成功,就拿到了锁,这样就可以允许少数节点挂掉了。整个取锁、释放锁的操作和单节点类似

 Redisson实现案例(代码来着官方GitHub)

基于Redis的Redisson红锁RedissonRedLock对象实现了Redlock介绍的加锁算法。该对象也可以用来将多个RLock对象关联为一个红锁,每个RLock对象实例可以来自于不同的Redisson实例。

RLock lock1 = redissonInstance1.getLock("lock1");
RLock lock2 = redissonInstance2.getLock("lock2");
RLock lock3 = redissonInstance3.getLock("lock3");

RedissonRedLock lock = new RedissonRedLock(lock1, lock2, lock3);
// 同时加锁:lock1 lock2 lock3
// 红锁在大部分节点上加锁成功就算成功。
lock.lock();
...
lock.unlock();

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

另外Redisson还通过加锁的方法提供了leaseTime的参数来指定加锁的时间。超过这个时间后锁便自动解开了。

RedissonRedLock lock = new RedissonRedLock(lock1, lock2, lock3);
// 给lock1,lock2,lock3加锁,如果没有手动解开的话,10秒钟后将会自动解开
lock.lock(10, TimeUnit.SECONDS);

// 为加锁等待100秒时间,并在加锁成功10秒钟后自动解开
boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
...
lock.unlock();

https://github.com/redisson/redisson/wiki/8.-%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81%E5%92%8C%E5%90%8C%E6%AD%A5%E5%99%A8#84-%E7%BA%A2%E9%94%81redlock

使用方式 

pom引入

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.13.0</version>
</dependency>

简单栗子

public class RedissonConfig {
   static Config config = new Config();
   static {
       config.useSingleServer()
       //config.useReplicatedServers()
         //      .setScanInterval(2000) // 主节点变化扫描间隔时间
               //可以用"rediss://"来启用SSL连接
               .setAddress("redis://127.0.0.1:6379");
   }
    RedissonClient redisson;
public static void main(String[] args) {
    RedissonClient redissonClient = new RedissonConfig().getRedisson();
    RLock lock1 = redissonClient.getLock("test");
    RedissonRedLock lock = new RedissonRedLock(lock1);
    // 加锁,如果没有手动解开的话,10秒钟后将会自动解开
    lock.lock(10, TimeUnit.SECONDS);

    try {
        // 为加锁等待100秒时间,并在加锁成功10秒钟后自动解开
        boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
        if(!res){
            System.out.println("枷锁失败");
        return;
        }
        执行业务(需要锁定的部分)
        System.out.println("业务代码");
    }catch (Exception e){
        e.printStackTrace();
    }finally {
        lock.unlock();
    }


}
   public RedissonConfig(){
       redisson = Redisson.create(config);
   }

    public static Config getConfig() {
        return config;
    }

    public static void setConfig(Config config) {
        RedissonConfig.config = config;
    }

    public RedissonClient getRedisson() {
        return redisson;
    }

    public void setRedisson(RedissonClient redisson) {
        this.redisson = redisson;
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值