一、介绍
Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的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),从而让使用者能够将精力更集中地放在处理业务逻辑上。
二、配置
1、程序配置方式
通过类代码来构建配置:通过构建Config对象实例来实现的。
1 | Config config = new Config(); |
2、配置文件方式
Redisson的配置文件可以是JSON格式或YAML格式。 可以通过调用Config.fromJSON方法并指定一个File实例来实现读取JSON格式的配置:
1 | Config config = Config.fromJSON(new File("config-file.json")); |
或
1 | Config config = Config.fromYAML(new File("config-file.yaml")); |
通过Spring XML命名空间配置
1 | <redisson:client> |
3、常用设置
以下是关于org.redisson.Config类的配置参数,它适用于所有Redis组态模式(单机,集群和哨兵)
codec(编码)
默认值: org.redisson.codec.JsonJacksonCodec
可选:
1 | 编码类名称 说明 |
threads(线程池数量)
默认值: 当前处理核数量 * 2
这个线程池数量被所有RTopic对象监听器,RRemoteService调用者和RExecutorService任务共同共享。
nettyThreads (Netty线程池数量)
默认值: 当前处理核数量 * 2
这个线程池数量是在一个Redisson实例内,被其创建的所有分布式数据类型和服务,以及底层客户端所一同共享的线程池里保存的线程数量。
executor(线程池)
单独提供一个用来执行所有RTopic对象监听器,RRemoteService调用者和RExecutorService任务的线程池(ExecutorService)实例。
eventLoopGroup
用于特别指定一个EventLoopGroup. EventLoopGroup是用来处理所有通过Netty与Redis服务之间的连接发送和接受的消息。每一个Redisson都会在默认情况下自己创建管理一个EventLoopGroup实例。因此,如果在同一个JVM里面可能存在多个Redisson实例的情况下,采取这个配置实现多个Redisson实例共享一个EventLoopGroup的目的。
只有io.netty.channel.epoll.EpollEventLoopGroup或io.netty.channel.nio.NioEventLoopGroup才是允许的类型。
transportMode(传输模式)
默认值:TransportMode.NIO
可选参数:
TransportMode.NIO,
TransportMode.EPOLL - 需要依赖里有netty-transport-native-epoll包(Linux) TransportMode.KQUEUE - 需要依赖里有 netty-transport-native-kqueue包(macOS)
lockWatchdogTimeout(监控锁的看门狗超时,单位:毫秒)
默认值:30000
监控锁的看门狗超时时间单位为毫秒。该参数只适用于分布式锁的加锁请求中未明确使用leaseTimeout参数的情况。如果该看门口未使用lockWatchdogTimeout去重新调整一个分布式锁的lockWatchdogTimeout超时,那么这个锁将变为失效状态。这个参数可以用来避免由Redisson客户端节点宕机或其他原因造成死锁的情况。
keepPubSubOrder(保持订阅发布顺序)
默认值:true
通过该参数来修改是否按订阅发布消息的接收顺序出来消息,如果选否将对消息实行并行处理,该参数只适用于订阅发布消息的情况。
performanceMode(高性能模式)
默认值:HIGHER_THROUGHPUT
用来指定高性能引擎的行为。由于该变量值的选用与使用场景息息相关(NORMAL除外)我们建议对每个参数值都进行尝试。
该参数仅限于Redisson PRO版本。
可选模式:
HIGHER_THROUGHPUT - 将高性能引擎切换到 高通量 模式。 LOWER_LATENCY_AUTO - 将高性能引擎切换到 低延时 模式并自动探测最佳设定。 LOWER_LATENCY_MODE_1 - 将高性能引擎切换到 低延时 模式并调整到预设模式1。 LOWER_LATENCY_MODE_2 - 将高性能引擎切换到 低延时 模式并调整到预设模式2。 NORMAL - 将高性能引擎切换到 普通 模式
集群模式
1、程序方式
1 | Config config = new Config(); |
2、通过文件配置集群模式
1 | { |
或
1 | clusterServersConfig: |
1 | <redisson:client |
3、设置
Redis集群组态的最低要求是必须有三个主节点。Redisson的集群模式的使用方法如下:ClusterServersConfig clusterConfig = config.useClusterServers();
ClusterServersConfig 类的设置参数如下:
nodeAddresses(添加节点地址)
可以通过host:port的格式来添加Redis集群节点的地址。多个节点可以一次性批量添加。
scanInterval(集群扫描间隔时间)
默认值: 1000
对Redis集群节点状态扫描的时间间隔。单位是毫秒。
slots(分片数量)
默认值: 231 用于指定数据分片过程中的分片数量。支持数据分片/框架结构有:集(Set)、映射(Map)、BitSet、Bloom filter, Spring Cache和Hibernate Cache等.
readMode(读取操作的负载均衡模式)
默认值: SLAVE(只在从服务节点里读取)
注:在从服务节点里读取的数据说明已经至少有两个节点保存了该数据,确保了数据的高可用性。
设置读取操作选择节点的模式。 可用值为: SLAVE - 只在从服务节点里读取。 MASTER - 只在主服务节点里读取。 MASTER_SLAVE - 在主从服务节点里都可以读取。
subscriptionMode(订阅操作的负载均衡模式)
默认值:SLAVE(只在从服务节点里订阅)
设置订阅操作选择节点的模式。 可用值为: SLAVE - 只在从服务节点里订阅。 MASTER - 只在主服务节点里订阅。
loadBalancer(负载均衡算法类的选择)
默认值: org.redisson.connection.balancer.RoundRobinLoadBalancer
在多Redis服务节点的环境里,可以选用以下几种负载均衡方式选择一个节点: org.redisson.connection.balancer.WeightedRoundRobinBalancer - 权重轮询调度算法 org.redisson.connection.balancer.RoundRobinLoadBalancer - 轮询调度算法 org.redisson.connection.balancer.RandomLoadBalancer - 随机调度算法
subscriptionConnectionMinimumIdleSize(从节点发布和订阅连接的最小空闲连接数)
默认值:1
多从节点的环境里,每个 从服务节点里用于发布和订阅连接的最小保持连接数(长连接)。Redisson内部经常通过发布和订阅来实现许多功能。长期保持一定数量的发布订阅连接是必须的。
subscriptionConnectionPoolSize(从节点发布和订阅连接池大小)
默认值:50
多从节点的环境里,每个 从服务节点里用于发布和订阅连接的连接池最大容量。连接池的连接数量自动弹性伸缩。
slaveConnectionMinimumIdleSize(从节点最小空闲连接数)
默认值:32
多从节点的环境里,每个 从服务节点里用于普通操作(非 发布和订阅)的最小保持连接数(长连接)。长期保持一定数量的连接有利于提高瞬时读取反映速度。
slaveConnectionPoolSize(从节点连接池大小)
默认值:64
多从节点的环境里,每个 从服务节点里用于普通操作(非 发布和订阅)连接的连接池最大容量。连接池的连接数量自动弹性伸缩。
masterConnectionMinimumIdleSize(主节点最小空闲连接数)
默认值:32
多节点的环境里,每个 主节点的最小保持连接数(长连接)。长期保持一定数量的连接有利于提高瞬时写入反应速度。
masterConnectionPoolSize(主节点连接池大小)
默认值:64
多主节点的环境里,每个 主节点的连接池最大容量。连接池的连接数量自动弹性伸缩。
idleConnectionTimeout(连接空闲超时,单位:毫秒)
默认值:10000
如果当前连接池里的连接数量超过了最小空闲连接数,而同时有连接空闲时间超过了该数值,那么这些连接将会自动被关闭,并从连接池里去掉。时间单位是毫秒。
connectTimeout(连接超时,单位:毫秒)
默认值:10000
同任何节点建立连接时的等待超时。时间单位是毫秒。
timeout(命令等待超时,单位:毫秒)
默认值:3000
等待节点回复命令的时间。该时间从命令发送成功时开始计时。
retryAttempts(命令失败重试次数)
默认值:3
如果尝试达到 retryAttempts(命令失败重试次数) 仍然不能将命令发送至某个指定的节点时,将抛出错误。如果尝试在此限制之内发送成功,则开始启用 timeout(命令等待超时) 计时。
retryInterval(命令重试发送时间间隔,单位:毫秒)
默认值:1500
在一条命令发送失败以后,等待重试发送的时间间隔。时间单位是毫秒。
reconnectionTimeout(重新连接时间间隔,单位:毫秒)
默认值:3000
当与某个节点的连接断开时,等待与其重新建立连接的时间间隔。时间单位是毫秒。
failedAttempts(执行失败最大次数)
默认值:3
在某个节点执行相同或不同命令时,连续 失败 failedAttempts(执行失败最大次数) 时,该节点将被从可用节点列表里清除,直到 reconnectionTimeout(重新连接时间间隔) 超时以后再次尝试。
password(密码)
默认值:null
用于节点身份验证的密码。
subscriptionsPerConnection(单个连接最大订阅数量)
默认值:5
每个连接的最大订阅数量。
clientName(客户端名称)
默认值:null
在Redis节点里显示的客户端名称。
sslEnableEndpointIdentification(启用SSL终端识别)
默认值:true
开启SSL终端识别能力。
sslProvider(SSL实现方式)
默认值:JDK
确定采用哪种方式(JDK或OPENSSL)来实现SSL连接。
sslTruststore(SSL信任证书库路径)
默认值:null
指定SSL信任证书库的路径。
sslTruststorePassword(SSL信任证书库密码)
默认值:null
指定SSL信任证书库的密码。
sslKeystore(SSL钥匙库路径)
默认值:null
指定SSL钥匙库的路径。
sslKeystorePassword(SSL钥匙库密码)
默认值:null
指定SSL钥匙库的密码。
单Redis节点模式
1、程序化配置
1 | // 默认连接地址 127.0.0.1:6379 |
2、单节点设置
SingleServerConfig 类的设置参数如下:
address(节点地址)
可以通过host:port的格式来指定节点地址。
subscriptionConnectionMinimumIdleSize(发布和订阅连接的最小空闲连接数)
默认值:1
用于发布和订阅连接的最小保持连接数(长连接)。Redisson内部经常通过发布和订阅来实现许多功能。长期保持一定数量的发布订阅连接是必须的。
subscriptionConnectionPoolSize(发布和订阅连接池大小)
默认值:50
用于发布和订阅连接的连接池最大容量。连接池的连接数量自动弹性伸缩。
connectionMinimumIdleSize(最小空闲连接数)
默认值:32
最小保持连接数(长连接)。长期保持一定数量的连接有利于提高瞬时写入反应速度。
connectionPoolSize(连接池大小)
默认值:64
连接池最大容量。连接池的连接数量自动弹性伸缩。
dnsMonitoring(是否启用DNS监测)
默认值:false
在启用该功能以后,Redisson将会监测DNS的变化情况。
dnsMonitoringInterval(DNS监测时间间隔,单位:毫秒)
默认值:5000
监测DNS的变化情况的时间间隔。
idleConnectionTimeout(连接空闲超时,单位:毫秒)
默认值:10000
如果当前连接池里的连接数量超过了最小空闲连接数,而同时有连接空闲时间超过了该数值,那么这些连接将会自动被关闭,并从连接池里去掉。时间单位是毫秒。
connectTimeout(连接超时,单位:毫秒)
默认值:10000
同节点建立连接时的等待超时。时间单位是毫秒。
timeout(命令等待超时,单位:毫秒)
默认值:3000
等待节点回复命令的时间。该时间从命令发送成功时开始计时。
retryAttempts(命令失败重试次数)
默认值:3
如果尝试达到 retryAttempts(命令失败重试次数) 仍然不能将命令发送至某个指定的节点时,将抛出错误。如果尝试在此限制之内发送成功,则开始启用 timeout(命令等待超时) 计时。
retryInterval(命令重试发送时间间隔,单位:毫秒)
默认值:1500
在一条命令发送失败以后,等待重试发送的时间间隔。时间单位是毫秒。
reconnectionTimeout(重新连接时间间隔,单位:毫秒)
默认值:3000
当与某个节点的连接断开时,等待与其重新建立连接的时间间隔。时间单位是毫秒。
failedAttempts(执行失败最大次数)
默认值:3
在某个节点执行相同或不同命令时,连续 失败 failedAttempts(执行失败最大次数) 时,该节点将被从可用节点列表里清除,直到 reconnectionTimeout(重新连接时间间隔) 超时以后再次尝试。
database(数据库编号)
默认值:0
尝试连接的数据库编号。
password(密码)
默认值:null
用于节点身份验证的密码。
subscriptionsPerConnection(单个连接最大订阅数量)
默认值:5
每个连接的最大订阅数量。
clientName(客户端名称)
默认值:null
在Redis节点里显示的客户端名称。
sslEnableEndpointIdentification(启用SSL终端识别)
默认值:true
开启SSL终端识别能力。
sslProvider(SSL实现方式)
默认值:JDK
确定采用哪种方式(JDK或OPENSSL)来实现SSL连接。
sslTruststore(SSL信任证书库路径)
默认值:null
指定SSL信任证书库的路径。
sslTruststorePassword(SSL信任证书库密码)
默认值:null
指定SSL信任证书库的密码。
sslKeystore(SSL钥匙库路径)
默认值:null
指定SSL钥匙库的路径。
sslKeystorePassword(SSL钥匙库密码)
默认值:null
指定SSL钥匙库的密码。
3、配置文件
配置单节点模式可以通过指定一个JSON格式的文件来实现。以下是JSON格式的配置文件样本。文件中的字段名称必须与SingleServerConfig和Config对象里的字段名称相符。
1 | { |
1 | singleServerConfig: |
1 | <redisson:client |
哨兵模式
1、程序化配置
1 | Config config = new Config(); |
2、设置
SentinelServersConfig 类的设置参数如下:
dnsMonitoringInterval(DNS监控间隔,单位:毫秒)
默认值:5000
用来指定检查节点DNS变化的时间间隔。使用的时候应该确保JVM里的DNS数据的缓存时间保持在足够低的范围才有意义。用-1来禁用该功能。
masterName(主服务器的名称)
主服务器的名称是哨兵进程中用来监测主从服务切换情况的。
addSentinelAddress(添加哨兵节点地址)
可以通过host:port的格式来指定哨兵节点的地址。多个节点可以一次性批量添加。
readMode(读取操作的负载均衡模式)
默认值: SLAVE(只在从服务节点里读取)
注:在从服务节点里读取的数据说明已经至少有两个节点保存了该数据,确保了数据的高可用性。
设置读取操作选择节点的模式。 可用值为: SLAVE - 只在从服务节点里读取。 MASTER - 只在主服务节点里读取。 MASTER_SLAVE - 在主从服务节点里都可以读取。
subscriptionMode(订阅操作的负载均衡模式)
默认值:SLAVE(只在从服务节点里订阅)
设置订阅操作选择节点的模式。 可用值为: SLAVE - 只在从服务节点里订阅。 MASTER - 只在主服务节点里订阅。
loadBalancer(负载均衡算法类的选择)
默认值: org.redisson.connection.balancer.RoundRobinLoadBalancer
在使用多个Redis服务节点的环境里,可以选用以下几种负载均衡方式选择一个节点: org.redisson.connection.balancer.WeightedRoundRobinBalancer - 权重轮询调度算法 org.redisson.connection.balancer.RoundRobinLoadBalancer - 轮询调度算法 org.redisson.connection.balancer.RandomLoadBalancer - 随机调度算法
subscriptionConnectionMinimumIdleSize(从节点发布和订阅连接的最小空闲连接数)
默认值:1
多从节点的环境里,每个 从服务节点里用于发布和订阅连接的最小保持连接数(长连接)。Redisson内部经常通过发布和订阅来实现许多功能。长期保持一定数量的发布订阅连接是必须的。
subscriptionConnectionPoolSize(从节点发布和订阅连接池大小)
默认值:50
多从节点的环境里,每个 从服务节点里用于发布和订阅连接的连接池最大容量。连接池的连接数量自动弹性伸缩。
slaveConnectionMinimumIdleSize(从节点最小空闲连接数)
默认值:32
多从节点的环境里,每个 从服务节点里用于普通操作(非 发布和订阅)的最小保持连接数(长连接)。长期保持一定数量的连接有利于提高瞬时读取反映速度。
slaveConnectionPoolSize(从节点连接池大小)
默认值:64
多从节点的环境里,每个 从服务节点里用于普通操作(非 发布和订阅)连接的连接池最大容量。连接池的连接数量自动弹性伸缩。
masterConnectionMinimumIdleSize(主节点最小空闲连接数)
默认值:32
多从节点的环境里,每个 主节点的最小保持连接数(长连接)。长期保持一定数量的连接有利于提高瞬时写入反应速度。
masterConnectionPoolSize(主节点连接池大小)
默认值:64
主节点的连接池最大容量。连接池的连接数量自动弹性伸缩。
idleConnectionTimeout(连接空闲超时,单位:毫秒)
默认值:10000
如果当前连接池里的连接数量超过了最小空闲连接数,而同时有连接空闲时间超过了该数值,那么这些连接将会自动被关闭,并从连接池里去掉。时间单位是毫秒。
connectTimeout(连接超时,单位:毫秒)
默认值:10000
同任何节点建立连接时的等待超时。时间单位是毫秒。
timeout(命令等待超时,单位:毫秒)
默认值:3000
等待节点回复命令的时间。该时间从命令发送成功时开始计时。
retryAttempts(命令失败重试次数)
默认值:3
如果尝试达到 retryAttempts(命令失败重试次数) 仍然不能将命令发送至某个指定的节点时,将抛出错误。如果尝试在此限制之内发送成功,则开始启用 timeout(命令等待超时) 计时。
retryInterval(命令重试发送时间间隔,单位:毫秒)
默认值:1500
在一条命令发送失败以后,等待重试发送的时间间隔。时间单位是毫秒。
reconnectionTimeout(重新连接时间间隔,单位:毫秒)
默认值:3000
当与某个节点的连接断开时,等待与其重新建立连接的时间间隔。时间单位是毫秒。
failedAttempts(执行失败最大次数)
默认值:3
在某个节点执行相同或不同命令时,连续 失败 failedAttempts(执行失败最大次数) 时,该节点将被从可用节点列表里清除,直到 reconnectionTimeout(重新连接时间间隔) 超时以后再次尝试。
database(数据库编号)
默认值:0
尝试连接的数据库编号。
password(密码)
默认值:null
用于节点身份验证的密码。
subscriptionsPerConnection(单个连接最大订阅数量)
默认值:5
每个连接的最大订阅数量。
clientName(客户端名称)
默认值:null
在Redis节点里显示的客户端名称。
sslEnableEndpointIdentification(启用SSL终端识别)
默认值:true
开启SSL终端识别能力。
sslProvider(SSL实现方式)
默认值:JDK
确定采用哪种方式(JDK或OPENSSL)来实现SSL连接。
sslTruststore(SSL信任证书库路径)
默认值:null
指定SSL信任证书库的路径。
sslTruststorePassword(SSL信任证书库密码)
默认值:null
指定SSL信任证书库的密码。
sslKeystore(SSL钥匙库路径)
默认值:null
指定SSL钥匙库的路径。
sslKeystorePassword(SSL钥匙库密码)
默认值:null
指定SSL钥匙库的密码。
3、配置文件
1 | { |
1 | sentinelServersConfig: |
1 | <redisson:client |
主从模式
1、程序化配置
1 | Config config = new Config(); |
2、主从模式设置
MasterSlaveServersConfig 类的设置参数如下:
dnsMonitoringInterval(DNS监控间隔,单位:毫秒)
默认值:5000
用来指定检查节点DNS变化的时间间隔。使用的时候应该确保JVM里的DNS数据的缓存时间保持在足够低的范围才有意义。用-1来禁用该功能。
masterAddress(主节点地址)
可以通过host:port的格式来指定主节点地址。
addSlaveAddress(添加从主节点地址)
可以通过host:port的格式来指定从节点的地址。多个节点可以一次性批量添加。
readMode(读取操作的负载均衡模式)
默认值: SLAVE(只在从服务节点里读取)
注:在从服务节点里读取的数据说明已经至少有两个节点保存了该数据,确保了数据的高可用性。
设置读取操作选择节点的模式。 可用值为: SLAVE - 只在从服务节点里读取。 MASTER - 只在主服务节点里读取。 MASTER_SLAVE - 在主从服务节点里都可以读取。
subscriptionMode(订阅操作的负载均衡模式)
默认值:SLAVE(只在从服务节点里订阅)
设置订阅操作选择节点的模式。 可用值为: SLAVE - 只在从服务节点里订阅。 MASTER - 只在主服务节点里订阅。
loadBalancer(负载均衡算法类的选择)
默认值: org.redisson.connection.balancer.RoundRobinLoadBalancer
在使用多个Redis服务节点的环境里,可以选用以下几种负载均衡方式选择一个节点: org.redisson.connection.balancer.WeightedRoundRobinBalancer - 权重轮询调度算法 org.redisson.connection.balancer.RoundRobinLoadBalancer - 轮询调度算法 org.redisson.connection.balancer.RandomLoadBalancer - 随机调度算法
subscriptionConnectionMinimumIdleSize(从节点发布和订阅连接的最小空闲连接数)
默认值:1
多从节点的环境里,每个 从服务节点里用于发布和订阅连接的最小保持连接数(长连接)。Redisson内部经常通过发布和订阅来实现许多功能。长期保持一定数量的发布订阅连接是必须的。
subscriptionConnectionPoolSize(从节点发布和订阅连接池大小)
默认值:50
多从节点的环境里,每个 从服务节点里用于发布和订阅连接的连接池最大容量。连接池的连接数量自动弹性伸缩。
slaveConnectionMinimumIdleSize(从节点最小空闲连接数)
默认值:32
多从节点的环境里,每个 从服务节点里用于普通操作(非 发布和订阅)的最小保持连接数(长连接)。长期保持一定数量的连接有利于提高瞬时读取反映速度。
slaveConnectionPoolSize(从节点连接池大小)
默认值:64
多从节点的环境里,每个 从服务节点里用于普通操作(非 发布和订阅)连接的连接池最大容量。连接池的连接数量自动弹性伸缩。
masterConnectionMinimumIdleSize(主节点最小空闲连接数)
默认值:32
多从节点的环境里,每个 主节点的最小保持连接数(长连接)。长期保持一定数量的连接有利于提高瞬时写入反应速度。
masterConnectionPoolSize(主节点连接池大小)
默认值:64
主节点的连接池最大容量。连接池的连接数量自动弹性伸缩。
idleConnectionTimeout(连接空闲超时,单位:毫秒)
默认值:10000
如果当前连接池里的连接数量超过了最小空闲连接数,而同时有连接空闲时间超过了该数值,那么这些连接将会自动被关闭,并从连接池里去掉。时间单位是毫秒。
connectTimeout(连接超时,单位:毫秒)
默认值:10000
同任何节点建立连接时的等待超时。时间单位是毫秒。
timeout(命令等待超时,单位:毫秒)
默认值:3000
等待节点回复命令的时间。该时间从命令发送成功时开始计时。
retryAttempts(命令失败重试次数)
默认值:3
如果尝试达到 retryAttempts(命令失败重试次数) 仍然不能将命令发送至某个指定的节点时,将抛出错误。如果尝试在此限制之内发送成功,则开始启用 timeout(命令等待超时) 计时。
retryInterval(命令重试发送时间间隔,单位:毫秒)
默认值:1500
在一条命令发送失败以后,等待重试发送的时间间隔。时间单位是毫秒。
reconnectionTimeout(重新连接时间间隔,单位:毫秒)
默认值:3000
当与某个节点的连接断开时,等待与其重新建立连接的时间间隔。时间单位是毫秒。
failedAttempts(执行失败最大次数)
默认值:3
在某个节点执行相同或不同命令时,连续 失败 failedAttempts(执行失败最大次数) 时,该节点将被从可用节点列表里清除,直到 reconnectionTimeout(重新连接时间间隔) 超时以后再次尝试。
database(数据库编号)
默认值:0
尝试连接的数据库编号。
password(密码)
默认值:null
用于节点身份验证的密码。
subscriptionsPerConnection(单个连接最大订阅数量)
默认值:5
每个连接的最大订阅数量。
clientName(客户端名称)
默认值:null
在Redis节点里显示的客户端名称。
sslEnableEndpointIdentification(启用SSL终端识别)
默认值:true
开启SSL终端识别能力。
sslProvider(SSL实现方式)
默认值:JDK
确定采用哪种方式(JDK或OPENSSL)来实现SSL连接。
sslTruststore(SSL信任证书库路径)
默认值:null
指定SSL信任证书库的路径。
sslTruststorePassword(SSL信任证书库密码)
默认值:null
指定SSL信任证书库的密码。
sslKeystore(SSL钥匙库路径)
默认值:null
指定SSL钥匙库的路径。
sslKeystorePassword(SSL钥匙库密码)
默认值:null
指定SSL钥匙库的密码。
3、文件配置主从模式
1 | { |
1 | masterSlaveServersConfig: |
1 | <redisson:client |
三、程序接口调用方式
RedissonClient、RedissonReactiveClient和RedissonRxClient实例本身和Redisson提供的所有分布式对象都是线程安全的。
Redisson为每个操作都提供了** 自动重试策略 **,当某个命令执行失败时,Redisson会自动进行重试。自动重试策略可以通过修改retryAttempts(默认值:3)参数和retryInterval(默认值:1000毫秒)参数来进行优化调整。当等待时间达到retryInterval指定的时间间隔以后,将自动重试下一次。全部重试失败以后将抛出错误。
Redisson框架提供的几乎所有对象都包含了同步和异步相互匹配的方法。这些对象都可以通过RedissonClient接口获取。同时还为大部分Redisson对象提供了满足异步流处理标准的程序接口RedissonReactiveClient。除此外还提供了RxJava2规范的RedissonRxClient程序接口。
以下是关于使用RAtomicLong对象的范例:
1 | RedissonClient client = Redisson.create(config); |
异步执行方式
几乎所有的Redisson对象都实现了一个异步接口,异步接口提供的方法名称与其同步接口的方法名称相互匹配。例如:
1 | // RAtomicLong接口继承了RAtomicLongAsync接口 |
异步流执行方式
Redisson为大多数分布式数据结构提供了满足Reactor项目的异步流处理标准的程序接口。该接口通过两种方式实现:
1 | 基于Project Reactor标准的实现方式。使用范例如下: |
单个集合数据分片
在集群模式下,Redisson为单个Redis集合类型提供了自动分片的功能。
Redisson提供的所有数据结构都支持在集群环境下使用,但每个数据结构只被保存在一个固定的槽内。Redisson PRO提供的自动分片功能能够将单个数据结构拆分,然后均匀的分布在整个集群里,而不是被挤在单一一个槽里。自动分片功能的优势主要有以下几点:
- 单个数据结构可以充分利用整个集群内存资源,而不是被某一个节点的内存限制。
- 将单个数据结构分片以后分布在集群中不同的节点里,不仅可以大幅提高读写性能,还能够保证读写性能随着集群的扩张而自动提升。
Redisson通过自身的分片算法,将一个大集合拆分为若干个片段(默认231个,分片数量范围是3 - 16834),然后将拆分后的片段均匀的分布到集群里各个节点里,保证每个节点分配到的片段数量大体相同。比如在默认情况下231个片段分到含有4个主节点的集群里,每个主节点将会分配到大约57个片段,同样的道理如果有5个主节点,每个节点会分配到大约46个片段。
目前支持的数据结构类型和服务包括集(Set)、映射(Map)、BitSet、布隆过滤器(Bloom Filter)、Spring Cache和Hibernate Cache。该功能仅限于Redisson PRO版本。
四、分布式对象
每个Redisson对象实例都会有一个与之对应的Redis数据实例,可以通过调用getName方法来取得Redis数据实例的名称(key)。
1 | RMap map = redisson.getMap("mymap"); |
通用对象桶(Object Bucket)
Redisson的分布式RBucketJava对象是一种通用对象桶可以用来存放任类型的对象。 除了同步接口外,还提供了异步(Async)、反射式(Reactive)和RxJava2标准的接口。
1 | RBucket<AnyObject> bucket = redisson.getBucket("anyObject"); |
二进制流(Binary Stream)
Redisson的分布式RBinaryStream Java对象同时提供了InputStream接口和OutputStream接口的实现。流的最大容量受Redis主节点的内存大小限制。
1 | RBinaryStream stream = redisson.getBinaryStream("anyStream"); |
地理空间对象桶(Geospatial Bucket)
Redisson的分布式RGeo Java对象是一种专门用来储存与地理位置有关的对象桶。除了同步接口外,还提供了异步(Async)、反射式(Reactive)和RxJava2标准的接口。
1 | RGeo<String> geo = redisson.getGeo("test"); |
BitSet
Redisson的分布式RBitSetJava对象采用了与java.util.BiteSet类似结构的设计风格。可以理解为它是一个分布式的可伸缩式位向量。需要注意的是RBitSet的大小受Redis限制,最大长度为4 294 967 295。除了同步接口外,还提供了异步(Async)、反射式(Reactive)和RxJava2标准的接口。
1 | RBitSet set = redisson.getBitSet("simpleBitset"); |
BitSet数据分片(Sharding)(分布式RoaringBitMap)
基于Redis的Redisson集群分布式BitSet通过RClusteredBitSet接口,为集群状态下的Redis环境提供了BitSet数据分片的功能。通过优化后更加有效的分布式RoaringBitMap算法,突破了原有的BitSet大小限制,达到了集群物理内存容量大小。在这里可以获取更多的内部信息。
1 | RClusteredBitSet set = redisson.getClusteredBitSet("simpleBitset"); |
原子整长形(AtomicLong)
Redisson的分布式整长形RAtomicLong对象和Java中的java.util.concurrent.atomic.AtomicLong对象类似。除了同步接口外,还提供了异步(Async)、反射式(Reactive)和RxJava2标准的接口。
1 | RAtomicLong atomicLong = redisson.getAtomicLong("myAtomicLong"); |
原子双精度浮点(AtomicDouble)
Redisson还提供了分布式原子双精度浮点RAtomicDouble,弥补了Java自身的不足。除了同步接口外,还提供了异步(Async)、反射式(Reactive)和RxJava2标准的接口。
1 | RAtomicDouble atomicDouble = redisson.getAtomicDouble("myAtomicDouble"); |
话题(订阅分发)
Redisson的分布式话题RTopic标准的接口。
1 | RTopic topic = redisson.getTopic("anyTopic"); |
// 在其他线程或JVM节点
RTopic topic = redisson.getTopic(“anyTopic”);
long clientsReceivedMessage = topic.publish(new SomeObject());
在Redis节点故障转移(主从切换)或断线重连以后,所有的话题监听器将自动完成话题的重新订阅。
模糊话题
Redisson的模糊话题RPatternTopic对象可以通过正式表达式来订阅多个话题。除了同步接口外,还提供了异步(Async)、反射式(Reactive)和RxJava2标准的接口。
1 | // 订阅所有满足`topic1.*`表达式的话题 |
在Redis节点故障转移(主从切换)或断线重连以后,所有的模糊话题监听器将自动完成话题的重新订阅。
布隆过滤器(Bloom Filter)
Redisson利用Redis实现了Java分布式布隆过滤器(Bloom Filter)。所含最大比特数量为2^32。
1 | RBloomFilter<SomeObject> bloomFilter = redisson.getBloomFilter("sample"); |
布隆过滤器数据分片(Sharding)
基于Redis的Redisson集群分布式布隆过滤器通过RClusteredBloomFilter接口,为集群状态下的Redis环境提供了布隆过滤器数据分片的功能。 通过优化后更加有效的算法,通过压缩未使用的比特位来释放集群内存空间。每个对象的状态都将被分布在整个集群中。所含最大比特数量为2^64。在这里可以获取更多的内部信息。
1 | RClusteredBloomFilter<SomeObject> bloomFilter = redisson.getClusteredBloomFilter("sample"); |
基数估计算法(HyperLogLog)
Redisson利用Redis实现了Java分布式基数估计算法(HyperLogLog)对象。该对象可以在有限的空间内通过概率算法统计大量的数据。除了同步接口外,还提供了异步(Async)、反射式(Reactive)和RxJava2标准的接口。
1 | RHyperLogLog<Integer> log = redisson.getHyperLogLog("log"); |
整长型累加器(LongAdder)
基于Redis的Redisson分布式整长型累加器(LongAdder)采用了与java.util.concurrent.atomic.LongAdder类似的接口。通过利用客户端内置的LongAdder对象,为分布式环境下递增和递减操作提供了很高得性能。据统计其性能最高比分布式AtomicLong对象快 12000 倍。完美适用于分布式统计计量场景。
1 | RLongAdder atomicLong = redisson.getLongAdder("myLongAdder"); |
双精度浮点累加器(DoubleAdder)
基于Redis的Redisson分布式双精度浮点累加器(DoubleAdder)采用了与java.util.concurrent.atomic.DoubleAdder类似的接口。通过利用客户端内置的DoubleAdder对象,为分布式环境下递增和递减操作提供了很高得性能。据统计其性能最高比分布式AtomicDouble对象快 12000 倍。完美适用于分布式统计计量场景。
1 | RLongDouble atomicDouble = redisson.getLongDouble("myLongDouble"); |
当不再使用双精度浮点累加器对象的时候应该自行手动销毁,如果Redisson对象被关闭(shutdown)了,则不用手动销毁。
限流器(RateLimiter)
基于Redis的分布式限流器(RateLimiter)可以用来在分布式环境下现在请求方的调用频率。既适用于不同Redisson实例下的多线程限流,也适用于相同Redisson实例下的多线程限流。该算法不保证公平性。除了同步接口外,还提供了异步(Async)、反射式(Reactive)和RxJava2标准的接口。
1 | RRateLimiter rateLimiter = redisson.getRateLimiter("myRateLimiter"); |
五、分布式集合
1、映射(Map)
基于Redis的Redisson的分布式映射结构的RMap Java对象实现了java.util.concurrent.ConcurrentMap接口和java.util.Map接口。与HashMap不同的是,RMap保持了元素的插入顺序。该对象的最大容量受Redis限制,最大元素数量是4 294 967 295个。
除了同步接口外,还提供了异步(Async)、反射式(Reactive)和RxJava2标准的接口。如果你想用Redis Map来保存你的POJO的话,可以考虑使用分布式实时对象(Live Object)服务。
在特定的场景下,映射缓存(Map)上的高度频繁的读取操作,使网络通信都被视为瓶颈时,可以使用Redisson提供的带有本地缓存功能的映射。
1 | RMap<String, SomeObject> map = redisson.getMap("anyMap"); |
映射的字段锁的用法:
1 | RMap<MyKey, MyValue> map = redisson.getMap("anyMap"); |
映射(Map)的元素淘汰(Eviction),本地缓存(LocalCache)和数据分片(Sharding)
Redisson提供了一系列的映射类型的数据结构,这些结构按特性主要分为三大类:
*元素淘汰(Eviction) *类 – 带有元素淘汰(Eviction)机制的映射类允许针对一个映射中每个元素单独设定 有效时间 和 最长闲置时间 。
本地缓存(LocalCache) 类 – 本地缓存(Local Cache)也叫就近缓存(Near Cache)。这类映射的使用主要用于在特定的场景下,映射缓存(MapCache)上的高度频繁的读取操作,使网络通信都被视为瓶颈的情况。Redisson与Redis通信的同时,还将部分数据保存在本地内存里。这样的设计的好处是它能将读取速度提高最多 45倍 。 所有同名的本地缓存共用一个订阅发布话题,所有更新和过期消息都将通过该话题共享。
数据分片(Sharding) 类 – 数据分片(Sharding)类仅适用于Redis集群环境下,因此带有数据分片(Sharding)功能的映射也叫集群分布式映射。它利用分库的原理,将单一一个映射结构切分为若干个小的映射,并均匀的分布在集群中的各个槽里。这样的设计能使一个单一映射结构突破Redis自身的容量限制,让其容量随集群的扩大而增长。在扩容的同时,还能够使读写性能和元素淘汰处理能力随之成线性增长。
以下列表是Redisson提供的所有映射的名称及其特性:
1 | 接口名称 |
元素淘汰功能(Eviction)
Redisson的分布式的RMapCache Java对象在基于RMap的前提下实现了针对单个元素的淘汰机制。同时仍然保留了元素的插入顺序。由于RMapCache是基于RMap实现的,使它同时继承了java.util.concurrent.ConcurrentMap接口和java.util.Map接口。Redisson提供的Spring Cache整合以及JCache正是基于这样的功能来实现的。
目前的Redis自身并不支持散列(Hash)当中的元素淘汰,因此所有过期元素都是通过org.redisson.EvictionScheduler实例来实现定期清理的。为了保证资源的有效利用,每次运行最多清理300个过期元素。任务的启动时间将根据上次实际清理数量自动调整,间隔时间趋于1秒到1小时之间。比如该次清理时删除了300条元素,那么下次执行清理的时间将在1秒以后(最小间隔时间)。一旦该次清理数量少于上次清理数量,时间间隔将增加1.5倍。
1 | RMapCache<String, SomeObject> map = redisson.getMapCache("anyMap"); |
本地缓存功能(Local Cache)
在特定的场景下,映射(Map)上的高度频繁的读取操作,使网络通信都被视为瓶颈时,使用Redisson提供的带有本地缓存功能的分布式本地缓存映射RLocalCachedMapJava对象会是一个很好的选择。它同时实现了java.util.concurrent.ConcurrentMap和java.util.Map两个接口。本地缓存功能充分的利用了JVM的自身内存空间,对部分常用的元素实行就地缓存,这样的设计让读取操作的性能较分布式映射相比提高最多 45倍 。以下配置参数可以用来创建这个实例:
1 | LocalCachedMapOptions options = LocalCachedMapOptions.defaults() |
当不再使用Map本地缓存对象的时候应该手动销毁,如果Redisson对象被关闭(shutdown)了,则不用手动销毁。
1 | RLocalCachedMap<String, Integer> map = ... |
数据分片功能(Sharding)
Map数据分片是Redis集群模式下的一个功能。Redisson提供的分布式集群映射RClusteredMap Java对象也是基于RMap实现的。它同时实现了java.util.concurrent.ConcurrentMap和java.util.Map两个接口。在这里可以获取更多的内部信息。
1 | RClusteredMap<String, SomeObject> map = redisson.getClusteredMap("anyMap"); |
映射持久化方式(缓存策略)
Redisson供了将映射中的数据持久化到外部储存服务的功能。主要场景有一下几种:
- 将Redisson的分布式映射类型作为业务和外部储存媒介之间的缓存。
- 或是用来增加Redisson映射类型中数据的持久性,或是用来增加已被驱逐的数据的寿命。
- 或是用来缓存数据库,Web服务或其他数据源的数据。
Read-through策略
通俗的讲,如果一个被请求的数据不存在于Redisson的映射中的时候,Redisson将通过预先配置好的MapLoader对象加载数据。
Write-through(数据同步写入)策略
在遇到映射中某条数据被更改时,Redisson会首先通过预先配置好的MapWriter对象写入到外部储存系统,然后再更新Redis内的数据。
Write-behind(数据异步写入)策略
对映射的数据的更改会首先写入到Redis,然后再使用异步的方式,通过MapWriter对象写入到外部储存系统。在并发环境下可以通过writeBehindThreads参数来控制写入线程的数量,已达到对外部储存系统写入并发量的控制。
以上策略适用于所有实现了RMap、RMapCache、RLocalCachedMap和RLocalCachedMapCache接口的对象。
配置范例:
1 | MapOptions<K, V> options = MapOptions.<K, V>defaults() |
映射监听器(Map Listener)
Redisson为所有实现了RMapCache或RLocalCachedMapCache接口的对象提供了监听以下事件的监听器:
- 事件 | 监听器 元素 添加 事件 | org.redisson.api.map.event.EntryCreatedListener
- 元素 过期 事件 | org.redisson.api.map.event.EntryExpiredListener
- 元素 删除 事件 | org.redisson.api.map.event.EntryRemovedListener
- 元素 更新 事件 | org.redisson.api.map.event.EntryUpdatedListener
使用范例:
1 | RMapCache<String, Integer> map = redisson.getMapCache("myMap"); |
LRU有界映射
Redisson提供了基于Redis的以LRU为驱逐策略的分布式LRU有界映射对象。顾名思义,分布式LRU有界映射允许通过对其中元素按使用时间排序处理的方式,主动移除超过规定容量限制的元素。
1 | RMapCache<String, String> map = redisson.getMapCache("map"); |
2、多值映射(Multimap)
基于Redis的Redisson的分布式RMultimap Java对象允许Map中的一个字段值包含多个元素。 字段总数受Redis限制,每个Multimap最多允许有4 294 967 295个不同字段。
基于集(Set)的多值映射(Multimap)
基于Set的Multimap不允许一个字段值包含有重复的元素。
RSetMultimap<SimpleKey, SimpleValue> map = redisson.getSetMultimap(“myMultimap”);
map.put(new SimpleKey(“0”), new SimpleValue(“1”));
map.put(new SimpleKey(“0”), new SimpleValue(“2”));
map.put(new SimpleKey(“3”), new SimpleValue(“4”));
Set
List
Set
Set
基于列表(List)的多值映射(Multimap)
基于List的Multimap在保持插入顺序的同时允许一个字段下包含重复的元素。
RListMultimap<SimpleKey, SimpleValue> map = redisson.getListMultimap(“test1”);
map.put(new SimpleKey(“0”), new SimpleValue(“1”));
map.put(new SimpleKey(“0”), new SimpleValue(“2”));
map.put(new SimpleKey(“0”), new SimpleValue(“1”));
map.put(new SimpleKey(“3”), new SimpleValue(“4”));
List
Collection
List
List
多值映射(Multimap)淘汰机制(Eviction)
Multimap对象的淘汰机制是通过不同的接口来实现的。它们是RSetMultimapCache接口和RListMultimapCache接口,分别对应的是Set和List的Multimaps。
所有过期元素都是通过org.redisson.EvictionScheduler实例来实现定期清理的。为了保证资源的有效利用,每次运行最多清理100个过期元素。任务的启动时间将根据上次实际清理数量自动调整,间隔时间趋于1秒到2小时之间。比如该次清理时删除了100条元素,那么下次执行清理的时间将在1秒以后(最小间隔时间)。一旦该次清理数量少于上次清理数量,时间间隔将增加1.5倍。
RSetMultimapCache的使用范例:
1 | RSetMultimapCache<String, String> multimap = redisson.getSetMultimapCache("myMultimap"); |
3、集(Set)
基于Redis的Redisson的分布式Set结构的RSet Java对象实现了java.util.Set接口。通过元素的相互状态比较保证了每个元素的唯一性。该对象的最大容量受Redis限制,最大元素数量是4 294 967 295个。
1 | RSet<SomeObject> set = redisson.getSet("anySet"); |
集(Set)淘汰机制(Eviction)
基于Redis的Redisson的分布式RSetCache Java对象在基于RSet的前提下实现了针对单个元素的淘汰机制。由于RSetCache是基于RSet实现的,使它还集成了java.util.Set接口。
目前的Redis自身并不支持Set当中的元素淘汰,因此所有过期元素都是通过org.redisson.EvictionScheduler实例来实现定期清理的。为了保证资源的有效利用,每次运行最多清理100个过期元素。任务的启动时间将根据上次实际清理数量自动调整,间隔时间趋于1秒到2小时之间。比如该次清理时删除了100条元素,那么下次执行清理的时间将在1秒以后(最小间隔时间)。一旦该次清理数量少于上次清理数量,时间间隔将增加1.5倍。
1 | RSetCache<SomeObject> set = redisson.getSetCache("anySet"); |
集(Set)数据分片(Sharding)
Set数据分片是Redis集群模式下的一个功能。Redisson提供的分布式RClusteredSet Java对象也是基于RSet实现的。在这里可以获取更多的信息。
1 | RClusteredSet<SomeObject> set = redisson.getClusteredSet("anySet"); |
除了RClusteredSet以外,Redisson还提供了另一种集群模式下的分布式集(Set),它不仅提供了透明的数据分片功能,还为每个元素提供了淘汰机制。RClusteredSetCache 类分别同时提供了RClusteredSet 和RSetCache 这两个接口的实现。当然这些都是基于java.util.Set的接口实现上的。
该功能仅限于Redisson PRO版本。
4、有序集(SortedSet)
基于Redis的Redisson的分布式RSortedSet Java对象实现了java.util.SortedSet接口。在保证元素唯一性的前提下,通过比较器(Comparator)接口实现了对元素的排序。
1 | RSortedSet<Integer> set = redisson.getSortedSet("anySet"); |
5、计分排序集(ScoredSortedSet)
基于Redis的Redisson的分布式RScoredSortedSet Java对象是一个可以按插入时指定的元素评分排序的集合。它同时还保证了元素的唯一性。
1 | RScoredSortedSet<SomeObject> set = redisson.getScoredSortedSet("simple"); |
6、字典排序集(LexSortedSet)
基于Redis的Redisson的分布式RLexSortedSet Java对象在实现了java.util.Set
1 | RLexSortedSet set = redisson.getLexSortedSet("simple"); |
7、列表(List)
基于Redis的Redisson分布式列表(List)结构的RList Java对象在实现了java.util.List接口的同时,确保了元素插入时的顺序。该对象的最大容量受Redis限制,最大元素数量是4 294 967 295个。
1 | RList<SomeObject> list = redisson.getList("anyList"); |
8、队列(Queue)
基于Redis的Redisson分布式无界队列(Queue)结构的RQueue Java对象实现了java.util.Queue接口。尽管RQueue对象无初始大小(边界)限制,但对象的最大容量受Redis限制,最大元素数量是4 294 967 295个。
1 | RQueue<SomeObject> queue = redisson.getQueue("anyQueue"); |
9、双端队列(Deque)
基于Redis的Redisson分布式无界双端队列(Deque)结构的RDeque Java对象实现了java.util.Deque接口。尽管RDeque对象无初始大小(边界)限制,但对象的最大容量受Redis限制,最大元素数量是4 294 967 295个。
1 | RDeque<SomeObject> queue = redisson.getDeque("anyDeque"); |
10、阻塞队列(Blocking Queue)
基于Redis的Redisson分布式无界阻塞队列(Blocking Queue)结构的RBlockingQueue Java对象实现了java.util.concurrent.BlockingQueue接口。尽管RBlockingQueue对象无初始大小(边界)限制,但对象的最大容量受Redis限制,最大元素数量是4 294 967 295个。
1 | RBlockingQueue<SomeObject> queue = redisson.getBlockingQueue("anyQueue"); |
poll, pollFromAny, pollLastAndOfferFirstTo和take方法内部采用话题订阅发布实现,在Redis节点故障转移(主从切换)或断线重连以后,内置的相关话题监听器将自动完成话题的重新订阅。
11、有界阻塞队列(Bounded Blocking Queue)
基于Redis的Redisson分布式有界阻塞队列(Bounded Blocking Queue)结构的RBoundedBlockingQueue Java对象实现了java.util.concurrent.BlockingQueue接口。该对象的最大容量受Redis限制,最大元素数量是4 294 967 295个。队列的初始容量(边界)必须在使用前设定好。
1 | RBoundedBlockingQueue<SomeObject> queue = redisson.getBoundedBlockingQueue("anyQueue"); |
poll, pollFromAny, pollLastAndOfferFirstTo和take方法内部采用话题订阅发布实现,在Redis节点故障转移(主从切换)或断线重连以后,内置的相关话题监听器将自动完成话题的重新订阅。
12. 阻塞双端队列(Blocking Deque)
基于Redis的Redisson分布式无界阻塞双端队列(Blocking Deque)结构的RBlockingDeque Java对象实现了java.util.concurrent.BlockingDeque接口。尽管RBlockingDeque对象无初始大小(边界)限制,但对象的最大容量受Redis限制,最大元素数量是4 294 967 295个。
1 | RBlockingDeque<Integer> deque = redisson.getBlockingDeque("anyDeque"); |
poll, pollFromAny, pollLastAndOfferFirstTo和take方法内部采用话题订阅发布实现,在Redis节点故障转移(主从切换)或断线重连以后,内置的相关话题监听器将自动完成话题的重新订阅。
13. 阻塞公平队列(Blocking Fair Queue)
基于Redis的Redisson分布式无界阻塞公平队列(Blocking Fair Queue)结构的RBlockingFairQueue Java对象在实现Redisson分布式无界阻塞队列(Blocking Queue)结构RBlockingQueue接口的基础上,解决了多个队列消息的处理者在复杂的网络环境下,网络延时的影响使“较远”的客户端最终收到消息数量低于“较近”的客户端的问题。从而解决了这种现象引发的个别处理节点过载的情况。
以分布式无界阻塞队列为基础,采用公平获取消息的机制,不仅保证了poll、pollFromAny、pollLastAndOfferFirstTo和take方法获取消息的先入顺序,还能让队列里的消息被均匀的发布到处在复杂分布式环境中的各个处理节点里。
1 | RBlockingFairQueue queue = redisson.getBlockingFairQueue("myQueue"); |
该功能仅限于Redisson PRO版本。
14. 阻塞公平双端队列(Blocking Fair Deque)
基于Redis的Redisson分布式无界阻塞公平双端队列(Blocking Fair Deque)结构的RBlockingFairDeque Java对象在实现Redisson分布式无界阻塞双端队列(Blocking Deque)结构RBlockingDeque接口的基础上,解决了多个队列消息的处理者在复杂的网络环境下,网络延时的影响使“较远”的客户端最终收到消息数量低于“较近”的客户端的问题。从而解决了这种现象引发的个别处理节点过载的情况。
以分布式无界阻塞双端队列为基础,采用公平获取消息的机制,不仅保证了poll、take、pollFirst、takeFirst、pollLast和takeLast方法获取消息的先入顺序,还能让队列里的消息被均匀的发布到处在复杂分布式环境中的各个处理节点里。
1 | RBlockingFairDeque deque = redisson.getBlockingFairDeque("myDeque"); |
该功能仅限于Redisson PRO版本。
15. 延迟队列(Delayed Queue)
基于Redis的Redisson分布式延迟队列(Delayed Queue)结构的RDelayedQueue Java对象在实现了RQueue接口的基础上提供了向队列按要求延迟添加项目的功能。该功能可以用来实现消息传送延迟按几何增长或几何衰减的发送策略。
1 | RQueue<String> distinationQueue = ... |
16. 优先队列(Priority Queue)
基于Redis的Redisson分布式优先队列(Priority Queue)Java对象实现了java.util.Queue的接口。可以通过比较器(Comparator)接口来对元素排序。
1 | RPriorityQueue<Integer> queue = redisson.getPriorityQueue("anyQueue"); |
17. 优先双端队列(Priority Deque)
基于Redis的Redisson分布式优先双端队列(Priority Deque)Java对象实现了java.util.Deque的接口。可以通过比较器(Comparator)接口来对元素排序。
1 | RPriorityDeque<Integer> queue = redisson.getPriorityDeque("anyQueue"); |
18. 优先阻塞队列(Priority Blocking Queue)
基于Redis的分布式无界优先阻塞队列(Priority Blocking Queue)Java对象的结构与java.util.concurrent.PriorityBlockingQueue类似。可以通过比较器(Comparator)接口来对元素排序。PriorityBlockingQueue的最大容量是4 294 967 295个元素。
1 | RPriorityBlockingQueue<Integer> queue = redisson.getPriorityBlockingQueue("anyQueue"); |
当Redis服务端断线重连以后,或Redis服务端发生主从切换,并重新建立连接后,断线时正在使用poll,pollLastAndOfferFirstTo或take方法的对象Redisson将自动再次为其订阅相关的话题。
19. 优先阻塞双端队列(Priority Blocking Deque)
基于Redis的分布式无界优先阻塞双端队列(Priority Blocking Deque)Java对象实现了java.util.Deque的接口。addLast、 addFirst、push方法不能再这个对里使用。PriorityBlockingDeque的最大容量是4 294 967 295个元素。
1 | RPriorityBlockingDeque<Integer> queue = redisson.getPriorityBlockingDeque("anyQueue"); |
当Redis服务端断线重连以后,或Redis服务端发生主从切换,并重新建立连接后,断线时正在使用poll,pollLastAndOfferFirstTo或take方法的对象Redisson将自动再次为其订阅相关的话题。
六、分布式锁和同步器
1. 可重入锁(Reentrant Lock)
基于Redis的Redisson分布式可重入锁RLock Java对象实现了java.util.concurrent.locks.Lock接口。同时还提供了异步(Async)、反射式(Reactive)和RxJava2标准的接口。
1 | RLock lock = redisson.getLock("anyLock"); |
大家都知道,如果负责储存这个分布式锁的Redisson节点宕机以后,而且这个锁正好处于锁住的状态时,这个锁会出现锁死的状态。为了避免这种情况的发生,Redisson内部提供了一个监控锁的看门狗,它的作用是在Redisson实例被关闭前,不断的延长锁的有效期。默认情况下,看门狗的检查锁的超时时间是30秒钟,也可以通过修改Config.lockWatchdogTimeout来另行指定。
另外Redisson还通过加锁的方法提供了leaseTime的参数来指定加锁的时间。超过这个时间后锁便自动解开了。
1 | // 加锁以后10秒钟自动解锁 |
Redisson同时还为分布式锁提供了异步执行的相关方法:
1 | RLock lock = redisson.getLock("anyLock"); |
RLock对象完全符合Java的Lock规范。也就是说只有拥有锁的进程才能解锁,其他进程解锁则会抛出IllegalMonitorStateException错误。但是如果遇到需要其他进程也能解锁的情况,请使用分布式信号量Semaphore 对象.
2. 公平锁(Fair Lock)
基于Redis的Redisson分布式可重入公平锁也是实现了java.util.concurrent.locks.Lock接口的一种RLock对象。同时还提供了异步(Async)、反射式(Reactive)和RxJava2标准的接口。它保证了当多个Redisson客户端线程同时请求加锁时,优先分配给先发出请求的线程。所有请求线程会在一个队列中排队,当某个线程出现宕机时,Redisson会等待5秒后继续下一个线程,也就是说如果前面有5个线程都处于等待状态,那么后面的线程会等待至少25秒。
1 | RLock fairLock = redisson.getFairLock("anyLock"); |
另外Redisson还通过加锁的方法提供了leaseTime的参数来指定加锁的时间。超过这个时间后锁便自动解开了。
1 | // 10秒钟以后自动解锁 |
3. 联锁(MultiLock)
基于Redis的Redisson分布式联锁RedissonMultiLock对象可以将多个RLock对象关联为一个联锁,每个RLock对象实例可以来自于不同的Redisson实例。
1 | RLock lock1 = redissonInstance1.getLock("lock1"); |
另外Redisson还通过加锁的方法提供了leaseTime的参数来指定加锁的时间。超过这个时间后锁便自动解开了。
1 | RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3); |
4. 红锁(RedLock)
基于Redis的Redisson红锁RedissonRedLock对象实现了Redlock介绍的加锁算法。该对象也可以用来将多个RLock对象关联为一个红锁,每个RLock对象实例可以来自于不同的Redisson实例。
1 | RLock lock1 = redissonInstance1.getLock("lock1"); |
1 | RedissonRedLock lock = new RedissonRedLock(lock1, lock2, lock3); |
5. 读写锁(ReadWriteLock)
基于Redis的Redisson分布式可重入读写锁RReadWriteLock Java对象实现了java.util.concurrent.locks.ReadWriteLock接口。其中读锁和写锁都继承了RLock接口。
分布式可重入读写锁允许同时有多个读锁和一个写锁处于加锁状态。
1 | RReadWriteLock rwlock = redisson.getReadWriteLock("anyRWLock"); |
另外Redisson还通过加锁的方法提供了leaseTime的参数来指定加锁的时间。超过这个时间后锁便自动解开了。
1 | // 10秒钟以后自动解锁 |
6. 信号量(Semaphore)
基于Redis的Redisson的分布式信号量(Semaphore)Java对象RSemaphore采用了与java.util.concurrent.Semaphore相似的接口和用法。同时还提供了异步(Async)、反射式(Reactive)和RxJava2标准的接口。
1 | RSemaphore semaphore = redisson.getSemaphore("semaphore"); |
7. 可过期性信号量(PermitExpirableSemaphore)
基于Redis的Redisson可过期性信号量(PermitExpirableSemaphore)是在RSemaphore对象的基础上,为每个信号增加了一个过期时间。每个信号可以通过独立的ID来辨识,释放时只能通过提交这个ID才能释放。它提供了异步(Async)、反射式(Reactive)和RxJava2标准的接口。
1 | RPermitExpirableSemaphore semaphore = redisson.getPermitExpirableSemaphore("mySemaphore"); |
8. 闭锁(CountDownLatch)
基于Redisson的Redisson分布式闭锁(CountDownLatch)Java对象RCountDownLatch采用了与java.util.concurrent.CountDownLatch相似的接口和用法。
1 | RCountDownLatch latch = redisson.getCountDownLatch("anyCountDownLatch"); |
七、分布式服务
1. 分布式远程服务(Remote Service)
基于Redis的Java分布式远程服务,可以用来通过共享接口执行存在于另一个Redisson实例里的对象方法。换句话说就是通过Redis实现了Java的远程过程调用(RPC)。分布式远程服务基于可以用POJO对象,方法的参数和返回类不受限制,可以是任何类型。
分布式远程服务(Remote Service)提供了两种类型的RRemoteService实例:
服务端(远端)实例 - 用来执行远程方法(工作者实例即worker instance). 例如:
1 | RRemoteService remoteService = redisson.getRemoteService(); |
客户端(本地)实例 - 用来请求远程方法. 例如:
1 | RRemoteService remoteService = redisson.getRemoteService(); |
客户端和服务端必须使用一样的共享接口,生成两者的Redisson实例必须采用相同的连接配置。客户端和服务端实例可以运行在同一个JVM里,也可以是不同的。客户端和服务端的数量不收限制。(注意:尽管Redisson不做任何限制,但是Redis的限制仍然有效。)
在服务端工作者可用实例数量 大于1 的时候,将并行执行并发调用的远程方法。
并行执行工作者数量计算方法如下: T = R * N
T - 并行执行工作者总数 R - Redisson服务端数量 N - 注册服务端时指定的执行工作者数量
超过该数量的并发请求将在列队中等候执行。
在服务端工作者实例可用数量为 1 时,远程过程调用将会按 顺序执行。这种情况下,每次只有一个请求将会被执行,其他请求将在列队中等候执行。
分布式远程服务工作流程
分布式远程服务为每个注册接口建立了两个列队。一个列队用于请求,由服务端监听,另一个列队用于应答回执和结果回复,由客户端监听。应答回执用于判定该请求是否已经被接受。如果在指定的超时时间内没有被执行工作者执行将会抛出RemoteServiceAckTimeoutException错误。
下图描述了每次发起远程过程调用请求的工作流程。
发送即不管(Fire-and-Forget)模式和应答回执(Ack-Response)模式
分布式远程服务通过org.redisson.core.RemoteInvocationOptions类,为每个远程过程调用提供了一些可配置选项。这些选项可以用来指定和修改请求超时和选择跳过应答回执或结果的发送模式。例如:
1 | // 应答回执超时1秒钟,远程执行超时30秒钟 |
异步调用
远程过程调用也可以采用异步的方式执行。异步调用需要单独提交一个带有@RRemoteAsync注解(annotation)的异步接口类。异步接口方法签名必须与远程接口的方法签名相符。异步接口的返回类必须是org.redisson.api.RFuture对象或其子对象。在调用RRemoteService.get方法时将对异步接口的方法进行验证。异步接口无须包含所有的远程接口里的方法,只需要包含要求异步执行的方法即可。
1 | // 远程接口 |
** 取消异步调用 **
通过调用Future.cancel()方法可以非常方便的取消一个异步调用。分布式远程服务允许在三个阶段中任何一个阶段取消异步调用:
- 远程调用请求在列队中排队阶段
- 远程调用请求已经被分布式远程服务接受,还未发送应答回执,执行尚未开始。
- 远程调用请求已经在执行阶段
- 想要正确的处理第三个阶段,在服务端代码里应该检查Thread.currentThread().isInterrupted()的返回状态。范例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41// 远程接口
public interface MyRemoteInterface {
Long myBusyMethod(Long param1, String param2);
}
// 匹配远程接口的异步接口
@RRemoteAsync(MyRemoteInterface.class)
public interface MyRemoteInterfaceAsync {
RFuture<Long> myBusyMethod(Long param1, String param2);
}
// 远程接口的实现
public class MyRemoteServiceImpl implements MyRemoteInterface {
public Long myBusyMethod(Long param1, String param2) {
for (long i = 0; i < Long.MAX_VALUE; i++) {
iterations.incrementAndGet();
if (Thread.currentThread().isInterrupted()) {
System.out.println("interrupted! " + i);
return;
}
}
}
}
RRemoteService remoteService = redisson.getRemoteService();
ExecutorService executor = Executors.newFixedThreadPool(5);
// 注册远程服务的服务端的同时,通过单独指定的ExecutorService来配置执行线程池
MyRemoteInterface serviceImpl = new MyRemoteServiceImpl();
remoteService.register(MyRemoteInterface.class, serviceImpl, 5, executor);
// 异步调用方法
MyRemoteInterfaceAsync asyncService = remoteService.get(MyRemoteInterfaceAsync.class);
RFuture<Long> future = asyncService.myBusyMethod(1L, "someparam");
// 取消异步调用
future.cancel(true);2、分布式实时对象(Live Object)服务
介绍
分布式实时对象(Live Object) 可以被理解为一个功能强化后的Java对象。该对象不仅可以被一个JVM里的各个线程相引用,还可以被多个位于不同JVM里的线程同时引用。
Redisson分布式实时对象(Redisson Live Object,简称RLO)运用即时生成的代理类(Proxy),将一个指定的普通Java类里的所有字段,以及针对这些字段的操作全部映射到一个Redis Hash的数据结构,实现这种理念。每个字段的get和set方法最终被转译为针对同一个Redis Hash的hget和hset命令,从而使所有连接到同一个Redis节点的所有可以客户端同时对一个指定的对象进行操作。众所周知,一个对象的状态是由其内部的字段所赋的值来体现的,通过将这些值保存在一个像Redis这样的远程共享的空间的过程,把这个对象强化成了一个分布式对象。这个分布式对象就叫做Redisson分布式实时对象(Redisson Live Object,简称RLO)。
通过使用RLO,运行在不同服务器里的多个程序之间,共享一个对象实例变得和在单机程序里共享一个对象实例一样了。同时还避免了针对任何一个字段操作都需要将整个对象序列化和反序列化的繁琐,进而降低了程序开发的复杂性和其数据模型的复杂性:从任何一个客户端修改一个字段的值,处在其他服务器上的客户端即刻便能查看到。而且实现代码与单机程序代码无异。(连接到从节点的客户端仍然受Redis的最终一致性的特性限制)
鉴于Redis是一个单线程的程序,针对实时对象的所有的字段操作可以理解为全部是原子性操作,也就是说在读取一个字段的过程不会担心被其他线程所修改。
通过使用RLO,可以把Redis当作一个允许被多个JVM同时操作且不受GC影响的共享堆(Heap Space)。
使用方法
Redisson为分布式实时对象提供了一系列不同功能的注解,其中@REntity和@RId两个注解是分布式实时对象的必要条件。
1 | @REntity |
在开始使用分布式实时对象以前,需要先通过Redisson服务将指定的对象连接(attach),合并(merge)或持久化(persist)到Redis里。
1 | RLiveObjectService service = redisson.getLiveObjectService(); |
“parent”字段中包含了指向到另一个分布式实时对象的引用,它可以与包含类是同一类型也可以不同。Redisson内部采用了与Java的引用类似的方式保存这个关系,而非将全部对象序列化,可视为与普通的引用同等效果。
1 | //RLO对象: |
RLO的字段类型基本上无限制,可以是任何类型。比如Java util包里的集合类,Map类等,也可以是自定义的对象。只要指定的编码解码器能够对其进行编码和解码操作便可。
尽管RLO的字段类型基本上无限制,个别类型还是受限。注解了RId的字段类型不能是数组类(Array),比如int[],long[],double[],byte[]等等。
为了保证RLO的用法和普通Java对象的用法尽可能一直,Redisson分布式实时对象服务自动将以下普通Java对象转换成与之匹配的Redisson分布式对象RObject。
1 | 普通Java类 转换后的Redisson类 |
类型转换将按照从上至下的顺序匹配类型,例如LinkedList类同时实现了Deque,List和Queue,由于Deque排在靠上的位置,因此它将会被转换成一个RedissonDeque类型。
Redisson的分布式对象也采用类似的方式,将自身的状态储存于Redis当中,(几乎^)所有的状态改变都直接映射到Redis里,不在本地JVM中保留任何赋值。(^本地缓存对象除外,比如RLocalCachedMap)
高级使用方法
正如上述介绍,RLO类其实都是按需实时生成的代理(Proxy)类。生成的代理类和原类都一同缓存Redisson实例里。这个过程会消耗一些时间,在对耗时比较敏感的情况下,建议通过RedissonLiveObjectService提前注册所有的RLO类。这个服务也可以用来注销不再需要的RLO类,也可以用来查询一个类是否已经注册了。
1 | RLiveObjectService service = redisson.getLiveObjectService(); |
注解(Annotation)使用方法
@REntity
仅适用于类。通过指定@REntity的各个参数,可以详细的对每个RLO类实现特殊定制,以达到改变RLO对象的行为。
1 | namingScheme - 命名方案。命名方案规定了每个实例在Redis中对应key的名称。它不仅被用来与已存在的RLO建立关联,还被用来储存新建的RLO实例。默认采用Redisson自带的DefaultNamingScheme对象。 |
@RId
仅适用于字段。@RId注解只能用在具备区分实例的字段上,这类字段可以理解为一个类的id字段或主键字段。这个字段的值将被命名方案namingScheme用来与事先存在的RLO建立引用。加了该注解的字段是唯一在本地JVM里同时保存赋值的字段。一个类只能有一个字段包含@RId注解。
可以通过指定一个生成器generator策略来实现自动生成这个字段的值。默认不提供生成器。
@RIndex
仅适用于字段。用来指定可用于搜索的字段。可以通过RLiveObjectService.find方法来根据条件精细查找分布式实时对象。查询条件可以是含(IN),或(OR),和(AND)或相等(EQ)以及它们的任意组合。
使用范例如下:
1 | public class MyObject { |
@RObjectField
仅适用于字段。允许通过该注解中的namingScheme或codec来改变该字段的命名或编码方式,用来区别于@REntity中指定的预设方式。
@RCascade
仅适用于字段。用来指定包含于分布式实时对象字段内其它对象的级联操作方式。
可选的级联操作方式为如下:
1 | RCascadeType.ALL - 执行所有级联操作 |
使用限制
如上所述,带有RId注解字段的类型不能使数组类,这是因为目前默认的命名方案类DefaultNamingScheme还不能正确地将数组类序列化和反序列化。在改善了DefaultNamingScheme类的不足以后会考虑取消这个限制。另外由于带有RId注解的字段是用来指定Redis中映射的key的名称,因此组建一个只含有唯一一个字段的RLO类是毫无意义的。选用RBucket会更适合这样的场景。
3、分布式执行服务(Executor Service)
概述
Redisson的分布式执行服务实现了java.util.concurrent.ExecutorService接口,支持在不同的独立节点里执行基于java.util.concurrent.Callable接口或java.lang.Runnable接口或Lambda的任务。这样的任务也可以通过使用Redisson实例,实现对储存在Redis里的数据进行操作。Redisson分布式执行服务是最快速和有效执行分布式运算的方法。
任务
Redisson独立节点不要求任务的类在类路径里。他们会自动被Redisson独立节点的ClassLoader加载。因此每次执行一个新任务时,不需要重启Redisson独立节点。
采用Callable任务的范例:
1 | public class CallableTask implements Callable<Long> { |
采用Runnable任务的范例:
1 | public class RunnableTask implements Runnable { |
在创建ExecutorService时可以配置以下参数:
1 | ExecutorOptions options = ExecutorOptions.defaults() |
使用Lambda任务的范例:
1 | RExecutorService executorService = redisson.getExecutorService("myExecutor", options); |
可以通过@RInject注解来为任务实时注入Redisson实例依赖。
取消任务
通过Future.cancel()方法可以很方便的取消所有已提交的任务。通过对Thread.currentThread().isInterrupted()方法的调用可以在已经处于运行状态的任务里实现任务中断:
1 | public class CallableTask implements Callable<Long> { |
4、分布式调度任务服务(Scheduler Service)
分布式调度任务服务概述
Redisson的分布式调度任务服务实现了java.util.concurrent.ScheduledExecutorService接口,支持在不同的独立节点里执行基于java.util.concurrent.Callable接口或java.lang.Runnable接口的任务。Redisson独立节点按顺序运行Redis列队里的任务。调度任务是一种需要在未来某个指定时间运行一次或多次的特殊任务。
设定任务计划
Redisson独立节点不要求任务的类在类路径里。他们会自动被Redisson独立节点的ClassLoader加载。因此每次执行一个新任务时,不需要重启Redisson独立节点。
采用Callable任务的范例:
1 | public class CallableTask implements Callable<Long> { |
在创建ExecutorService时可以配置以下参数:
1 | ExecutorOptions options = ExecutorOptions.defaults() |
使用Lambda任务的范例:
1 | RExecutorService executorService = redisson.getExecutorService("myExecutor", options); |
采用Runnable任务的范例:
1 | public class RunnableTask implements Runnable { |
通过CRON表达式设定任务计划
在分布式调度任务中,可以通过CRON表达式来为任务设定一个更复杂的计划。表达式与Quartz的CRON格式完全兼容。
1 | RScheduledExecutorService executorService = redisson.getExecutorService("myExecutor"); |
取消计划任务
分布式调度任务服务提供了两张取消任务的方式:通过调用ScheduledFuture.cancel()方法或调用RScheduledExecutorService.cancelScheduledTask方法。通过对Thread.currentThread().isInterrupted()方法的调用可以在已经处于运行状态的任务里实现任务中断:
1 | public class RunnableTask implements Callable<Long> { |
5、分布式映射归纳服务(MapReduce)
介绍
Redisson提供了通过映射归纳(MapReduce)编程模式来处理储存在Redis环境里的大量数据的服务。这个想法来至于其他的类似实现方式和谷歌发表的研究。所有 映射(Map) 和 归纳(Reduce) 阶段中的任务都是被分配到各个独立节点(Redisson Node)里并行执行的。以下所有接口均支持映射归纳(MapReduce)功能: RMap、 RMapCache、 RLocalCachedMap、 RSet、 RSetCache、 RList、 RSortedSet、 RScoredSortedSet、 RQueue、 RBlockingQueue、 RDeque、 RBlockingDeque、 RPriorityQueue 和 RPriorityDeque
映射归纳(MapReduce)的功能是通过RMapper、 RCollectionMapper、 RReducer 和 RCollator 这几个接口实现的。
- RMapper 映射器接口适用于映射(Map)类,它用来把映射(Map)中的每个元素转换为另一个作为归纳(Reduce)处理用的键值对。
1
2
3
4
5public interface RMapper<KIn, VIn, KOut, VOut> extends Serializable {
void map(KIn key, VIn value, RCollector<KOut, VOut> collector);
} - RCollectionMapper 映射器接口仅适用于集合(Collection)类型的对象,它用来把集合(Collection)中的元素转换成一组作为归纳(Reduce)处理用的键值对。
1
2
3
4
5public interface RCollectionMapper<VIn, KOut, VOut> extends Serializable {
void map(VIn value, RCollector<KOut, VOut> collector);
} - RReducer 归纳器接口用来将上面这些,由映射器生成的键值对列表进行归纳整理。
1
2
3
4
5public interface RReducer<K, V> extends Serializable {
V reduce(K reducedKey, Iterator<V> values);
} - RCollator 收集器接口用来把归纳整理以后的结果化简为单一一个对象。以上每个阶段的任务都可以用@RInject注解的方式来获取RedissonClient实例:
1
2
3
4
5public interface RCollator<K, V, R> extends Serializable {
R collate(Map<K, V> resultMap);
}1
2
3
4
5
6
7
8
9
10
11
12
13
14public class WordMapper implements RMapper<String, String, String, Integer> {
@RInject
private RedissonClient redissonClient;
@Override
public void map(String key, String value, RCollector<String, Integer> collector) {
// ...
redissonClient.getAtomicLong("mapInvocations").incrementAndGet();
}
}映射(Map)类型的使用范例
Redisson提供的RMap、 RMapCache和RLocalCachedMap这三种映射(Map)类型的对象均可以使用这种分布式映射归纳(MapReduce)服务。
以下是在映射(Map)类型的基础上采用映射归纳(MapReduce)来实现字数统计的范例:
Mapper对象将每个映射的值用空格且分开。
1 | public class WordMapper implements RMapper<String, String, String, Integer> { |
Reducer对象计算统计所有单词的使用情况。
1 | public class WordReducer implements RReducer<String, Integer> { |
Collator对象统计所有单词的使用情况。
1 | public class WordCollator implements RCollator<String, Integer, Integer> { |
把上面的各个对象串起来使用:
1 | RMap<String, String> map = redisson.getMap("wordsMap"); |
集合(Collection)类型的使用范例
Redisson提供的RSet、 RSetCache、 RList、 RSortedSet、 RScoredSortedSet、 RQueue、 RBlockingQueue、 RDeque、 RBlockingDeque、 RPriorityQueue和RPriorityDeque这几种集合(Collection)类型的对象均可以使用这种分布式映射归纳(MapReduce)服务。
以下是在集合(Collection)类型的基础上采用映射归纳(MapReduce)来实现字数统计的范例:
1 | public class WordMapper implements RCollectionMapper<String, String, Integer> { |
八、其他
1、对Redis节点的操作
Redisson的NodesGroup对象提供了许些对Redis节点的操作。
1 | NodesGroup nodesGroup = redisson.getNodesGroup(); |
2. 复杂多维对象结构和对象引用的支持
Redisson突破了Redis数据结构维度的限制,通过一个特殊引用对象的帮助,Redisson允许以任意的组合方式构建多维度的复杂对象结构,实现了对象之间的类似传统数据库里的关联关系。使用范例如下:
1 | RMap<RSet<RList>, RList<RMap>> map = redisson.getMap("myMap"); |
在map包含的元素发生改变以后,我们无需再次“保存/持久”这些对象。因为map对象所记录的并不是序列化以后的值,而是元素对象的引用。这让Redisson提供的对象在使用方法上,与普通Java对象的使用方法一致。从而让Redis成为内存的一部分,而不仅仅是一个储存空间。
以上范例中,一共创建了三个Redis数据结构:一个Redis HASH,一个Redis SET和一个Redis LIST。
3. 命令的批量执行
多个连续命令可以通过RBatch对象在一次网络会话请求里合并发送,这样省去了产生多个请求消耗的时间和资源。这在Redis中叫做管道。
用户可以通过以下方式调整通过管道方式发送命令的方式:
1 | BatchOptions options = BatchOptions.defaults() |
在集群模式下,所有的命令会按各个槽所在的节点,筛选分配到各个节点并同时发送。每个节点返回的结果将会汇总到最终的结果列表里。
4. Redisson事务
Redisson为RMap、RMapCache、RLocalCachedMap、RSet、RSetCache和RBucket这样的对象提供了具有ACID属性的事务功能。Redisson事务通过分布式锁保证了连续写入的原子性,同时在内部通过操作指令队列实现了Redis原本没有的提交与滚回功能。当提交与滚回遇到问题的时候,将通过org.redisson.transaction.TransactionException告知用户。
目前支持的环境如下: SINGLE, MASTER/SLAVE, SENTINEL, ELASTICACHE REPLICATED, AZURE CACHE, RLEC。
Redisson事务支持的事务隔离等级为: READ_COMMITTED,即仅读取提交后的结果。
另见 Spring事务管理器 和本章 XA事务(XA Transactions)。
以下选项可以用来配置事务属性:
1 | TransactionOptions options = TransactionOptions.defaults() |
5. XA事务(XA Transactions)
Redisson提供了XAResource标准的实现。该实现可用于JTA事务中。
另见本章Redisson事务和Spring事务管理器。
该功能仅适用于Redisson PRO版本
代码范例:
1 | // Transaction对象可以从所有兼容JTA接口的事务管理器中获取。 |
6. 脚本执行
1 | redisson.getBucket("foo").set("bar"); |