Redisson

2020-08-01

Spring Boot快速集成Redisson

使用redisson-spring-boot-starter快速上手,Redisson支持Redis 2.8以上版本,支持Java1.6+以上版本。

pom.xml

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>3.13.3</version>
</dependency>

application.yml

spring:
  profiles: dev
  redis:
    redisson:
      config: classpath:redisson-dev.yaml

redisson-dev.yaml

singleServerConfig:   # 单实例模式
  idleConnectionTimeout: 10000
  connectTimeout: 10000
  timeout: 3000
  retryAttempts: 3
  retryInterval: 1500
  password: null
  subscriptionsPerConnection: 1
  clientName: null
  address: "redis://127.0.0.1:6379"
  subscriptionConnectionMinimumIdleSize: 1
  subscriptionConnectionPoolSize: 1
  connectionMinimumIdleSize: 1
  connectionPoolSize: 5
  database: 0
  dnsMonitoringInterval: 5000
threads: 1
nettyThreads: 1
codec: null
transportMode: "NIO"
lockWatchdogTimeout: 30000  # 监控锁的看门狗超时,单位:毫秒

Redisson支持以下模式

集群模式

复制模式

单实例模式

哨兵模式

主从模式

代理模式

通用参数

threads

默认值:16

RTopic对象的所有侦听器RRemoteServiceRTopic对象和RExecutorService任务的调用处理程序之间共享的线程数量。

nettyThreads

默认值:32

Redisson使用的所有Redis客户端之间共享的线程数量。Redis响应解码和命令发送中使用的Netty线程。0=cores_amount * 2

codec

Redis数据编解码器。在读写Redis数据期间使用。几种实现方式提供

transportMode

默认值: TransportMode.NIO

可用值: TransportMode.NIO TransportMode.EPOLL - 需要netty-transport-native-epoll在类路径 TransportMode.KQUEUE - 需要netty-transport-native-kqueue在类路径

lockWatchdogTimeout(监控锁的看门狗超时,单位:毫秒)

默认值:30000

监控锁的看门狗超时时间单位为毫秒。该参数只适用于分布式锁的加锁请求中未明确使用leaseTimeout参数的情况。如果该看门狗未使用lockWatchdogTimeout去重新调整一个分布式锁的lockWatchdogTimeout超时,那么这个锁将变为失效状态。这个参数可以用来避免由Redisson客户端节点宕机或其他原因造成死锁的情况。

分布式锁

可重入锁

lock

/**
 * RLock分布式可重入锁,接口场景并发测试
 * @return
 */
@RequestMapping("lock2")
public R lock2() {
    RLock lock = redissonClient.getLock("redisson_lock2");
    lock.lock();
    lock.unlock();
    return R();
}

Redisson客户端节点宕机或出现异常会造成死锁,为了避免这种情况的发生,Redisson内部提供了一个监控锁的看门狗,它的作用是在Redisson实例被关闭前,不断的延长锁的有效期。默认情况下,看门狗的检查锁的超时时间是30秒,可修改配置参数lockWatchdogTimeout来重新指定。

指定自动解锁时间

注意:如果设置自动解锁时间,那么看门狗就失效了

// Redisson可通过加锁的方法提供的leaseTime的参数来指定加锁的时间,超过这个时间后锁便自动解开。
lock.lock(10, TimeUnit.SECONDS);

tryLock

/**
 * RLock分布式可重入锁,tryLock
 *
 * @return
 */
@RequestMapping("lock5")
public R lock5() throws InterruptedException {
    RLock lock = redissonClient.getLock("redisson_lock5");
    boolean getLockOK = lock.tryLock();
    if (getLockOK) {
        try {
            Thread.sleep(10 * 1000);
        } catch (InterruptedException ie) {
            ie.printStackTrace();
        } finally {
            lock.unlock();
        }
        return R("获取到锁");
    } else {
        return R("没有获取到锁");
    }
}

lock -> 调用后一直阻塞到获得锁

tryLock -> 尝试是否能获得锁 如果不能获得立即返回

lockInterruptibly -> 调用后一直阻塞到获得锁 但是接受中断信号

synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock 在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock 时需要在 finally块中释放锁。