Redisson突破了Redis数据结构维度的限制,通过一个特殊引用对象的帮助,Redisson允许以任意的组合方式构建多维度的复杂对象结构,实现了对象之间的类似传统数据库里的关联关系。使用范例如下:
可能您已经注意到了,在map包含的元素发生改变以后,我们无需再次“保存/持久”这些对象。因为map对象所记录的并不是序列化以后的值,而是元素对象的引用。这让Redisson提供的对象在使用方法上,与普通Java对象的使用方法一致。从而让Redis成为内存的一部分,而不仅仅是一个储存空间。
BatchOptions options = BatchOptions .defaults ()
// 指定执行模式
// ExecutionMode.REDIS_READ_ATOMIC - 所有命令缓存在Redis节点中,以原子性事务的方式执行。
// ExecutionMode.REDIS_WRITE_ATOMIC - 所有命令缓存在Redis节点中,以原子性事务的方式执行。
// ExecutionMode.IN_MEMORY - 所有命令缓存在Redisson本机内存中统一发送,但逐一执行(非事务)。默认模式。
// ExecutionMode.IN_MEMORY_ATOMIC - 所有命令缓存在Redisson本机内存中统一发送,并以原子性事务的方式执行。
.executionMode (ExecutionMode .IN_MEMORY )
// 告知Redis不用返回结果(可以减少网络用量)
.skipResult ()
// 将写入操作同步到从节点
// 同步到2个从节点,等待时间为1秒钟
.syncSlaves (2 , 1 , TimeUnit .SECONDS )
// 处理结果超时为2秒钟
.responseTimeout (2 , TimeUnit .SECONDS )
// 命令重试等待间隔时间为2秒钟
.retryInterval (2 , TimeUnit .SECONDS );
// 命令重试次数。仅适用于未发送成功的命令
.retryAttempts (4 );
RBatch batch = redisson.createBatch();
batch.getMap("test").fastPutAsync("1", "2");
batch.getMap("test").fastPutAsync("2", "3");
batch.getMap("test").putAsync("2", "5");
batch.getAtomicLongAsync("counter").incrementAndGetAsync();
batch.getAtomicLongAsync("counter").incrementAndGetAsync();
BatchResult res = batch.execute();
// 或者
Future<BatchResult> asyncRes = batch.executeAsync();
List<?> response = res.getResponses();
res.getSyncedSlaves();
在集群模式下,所有的命令会按各个槽所在的节点,筛选分配到各个节点并同时发送。每个节点返回的结果将会汇总到最终的结果列表里。
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) 。
以下选项可以用来配置事务属性:
TransactionOptions options = TransactionOptions .defaults ()
// 设置参与本次事务的主节点与其从节点同步的超时时间。
// 默认值是5秒。
.syncSlavesTimeout (5 , TimeUnit .SECONDS )
// 处理结果超时。
// 默认值是3秒。
.responseTimeout (3 , TimeUnit .SECONDS )
// 命令重试等待间隔时间。仅适用于未发送成功的命令。
// 默认值是1.5秒。
.retryInterval (2 , TimeUnit .SECONDS )
// 命令重试次数。仅适用于未发送成功的命令。
// 默认值是3次。
.retryAttempts (3 )
// 事务超时时间。如果规定时间内没有提交该事务则自动滚回。
// 默认值是5秒。
.timeout (5 , TimeUnit .SECONDS );
代码范例:
RTransaction transaction = redisson .createTransaction (TransactionOptions .defaults ());
RMap <String , String > map = transaction .getMap ("myMap" );
map .put ("1" , "2" );
String value = map .get ("3" );
RSet <String > set = transaction .getSet ("mySet" )
set .add (value );
try {
transaction .commit ();
} catch (TransactionException e ) {
transaction .rollback ();
10.5. XA事务(XA Transactions)
Redisson提供了XAResource 标准的实现。该实现可用于JTA事务中。
另见本章Redisson事务 和Spring事务管理器 。
该功能仅适用于Redisson PRO 版本
代码范例:
// Transaction对象可以从所有兼容JTA接口的事务管理器中获取。
Transaction globalTransaction = transactionManager .getTransaction ();
RXAResource xaResource = redisson .getXAResource ();
globalTransaction .enlistResource (xaResource );
RTransaction transaction = xaResource .getTransaction ();
RBucket <String > bucket = transaction .getBucket ("myBucket" );
bucket .set ("simple" );
RMap <String , String > map = transaction .getMap ("myMap" );
map .put ("myKey" , "myValue" );
transactionManager .commit ();
redisson .getBucket ("foo" ).set ("bar" );
String r = redisson .getScript ().eval (Mode .READ_ONLY ,
"return redis.call('get', 'foo')" , RScript .ReturnType .VALUE );
// 通过预存的脚本进行同样的操作
RScript s = redisson .getScript ();
// 首先将脚本保存到所有的Redis主节点
String res = s .scriptLoad ("return redis.call('get', 'foo')" );
// 返回值 res == 282297a0228f48cd3fc6a55de6316f31422f5d17
// 再通过SHA值调用脚本
Future <Object > r1 = redisson .getScript ().evalShaAsync (Mode .READ_ONLY ,
"282297a0228f48cd3fc6a55de6316f31422f5d17" ,
RScript .ReturnType .VALUE , Collections .emptyList ());
Redisson在底层采用了高性能异步非阻塞式Java客户端,它同时支持异步和同步两种通信模式。如果有哪些命令Redisson还没提供支持,也可以直接通过调用底层Redis客户端来实现。Redisson支持的命令在Redis命令和Redisson对象匹配列表 里做了详细对比参照。
// 在使用多个客户端的情况下可以共享同一个EventLoopGroup
EventLoopGroup group = new NioEventLoopGroup ();
RedisClientConfig config = new RedisClientConfig ();
config .setAddress ("redis://localhost:6379" ) // 或者用rediss://使用加密连接
.setPassword ("myPassword" )
.setDatabase (0 )
.setClientName ("myClient" )
.setGroup (group );
RedisClient client = RedisClient .create (config );
RedisConnection conn = client .connect ();
RFuture <RedisConnection > connFuture = client .connectAsync ();
conn .sync (StringCodec .INSTANCE , RedisCommands .SET , "test" , 0 );
conn .async (StringCodec .INSTANCE , RedisCommands .GET , "test" );
conn .close ()
conn .closeAsync ()
client .shutdown ();
client .shutdownAsync ();
280d386