赞
踩
- <dependency>
- <groupId>org.redisson</groupId>
- <artifactId>redisson-spring-boot-starter</artifactId>
- <version>3.23.5</version>
- </dependency>
redison-spring-boot-starter依赖于与最新版本的spring-boot兼容的redison-spring数据模块。降级redison弹簧数据模块(如有必要),以支持以前的spring Boot版本:
redisson-spring-data module name | Spring Boot version |
---|---|
redisson-spring-data-16 | 1.3.y |
redisson-spring-data-17 | 1.4.y |
redisson-spring-data-18 | 1.5.y |
redisson-spring-data-2x | 2.x.y |
redisson-spring-data-3x | 3.x.y |
使用 common Spring Boot 3.x+ settings:
- spring:
- data:
- redis:
- database:
- host:
- port:
- password:
- ssl:
- timeout:
- connectTimeout:
- clientName:
- cluster:
- nodes:
- sentinel:
- master:
- nodes:
使用common Spring Boot up to 2.7.x settings:
- spring:
- redis:
- database:
- host:
- port:
- password:
- ssl:
- timeout:
- connectTimeout:
- clientName:
- cluster:
- nodes:
- sentinel:
- master:
- nodes:
配置redision属性(application.yaml):
- spring:
- redis:
- redisson:
- config: |
- clusterServersConfig:
- idleConnectionTimeout: 10000
- connectTimeout: 10000
- timeout: 3000
- retryAttempts: 3
- retryInterval: 1500
- failedSlaveReconnectionInterval: 3000
- failedSlaveCheckInterval: 60000
- password: null
- subscriptionsPerConnection: 5
- clientName: null
- loadBalancer: !<org.redisson.connection.balancer.RoundRobinLoadBalancer> {}
- subscriptionConnectionMinimumIdleSize: 1
- subscriptionConnectionPoolSize: 50
- slaveConnectionMinimumIdleSize: 24
- slaveConnectionPoolSize: 64
- masterConnectionMinimumIdleSize: 24
- masterConnectionPoolSize: 64
- readMode: "SLAVE"
- subscriptionMode: "SLAVE"
- nodeAddresses:
- - "redis://127.0.0.1:7004"
- - "redis://127.0.0.1:7001"
- - "redis://127.0.0.1:7000"
- scanInterval: 1000
- pingConnectionInterval: 0
- keepAlive: false
- tcpNoDelay: false
- threads: 16
- nettyThreads: 32
- codec: !<org.redisson.codec.Kryo5Codec> {}
- transportMode: "NIO"
除了常用的 StringRedisTemplate
外,我们还可以注入如下由 Redisson 提供的 Bean:
RedissonClient
RedissonRxClient
(响应式)RedissonReactiveClient
(响应式)RedisTemplate
ReactiveRedisTemplate
(响应式)RedissonClient
来实现一个分布式锁,以进行测试:-
- import org.junit.jupiter.api.Test;
- import org.redisson.api.RedissonClient;
- import java.util.concurrent.CountDownLatch;
- import java.util.concurrent.locks.Lock;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.boot.test.context.SpringBootTest;
- import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
-
- @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
- public class Application {
-
- static final Logger logger = LoggerFactory.getLogger(DemoApplicationTests.class);
-
- // 注入 RedissonClient
- @Autowired
- RedissonClient redissonClient;
-
- // 计数器
- private int count;
-
- @Test
- public void LockOp throws InterruptedException {
-
- CountDownLatch countDownLatch = new CountDownLatch(1000);
-
- for (int i = 0; i < 1000; i++) {
-
- new Thread(() -> {
-
- // 每个线程都创建自己的锁对象
- // 这是基于 Redis 实现的分布式锁
- Lock lock = this.redissonClient.getLock("counterLock");
-
- try {
- // 上锁
- lock.lock();
-
- // 计数器自增 1
- this.count = this.count + 1;
-
- } finally {
- // 释放锁
- lock.unlock();
- }
- countDownLatch.countDown();
- }).start();
- }
-
- countDownLatch.await();
-
- logger.info("count = {}", this.count);
- }
如上。我们在测试类中注入了 RedissonClient
Bean,并且定义了一个 count
属性。在测试方法中,启动 1000 个线程对 count
属性进行 +1
操作。其中,每个线程都通过 RedissonClient
获取分布式锁来控制对变量的并发修改。
运行测试,输出的日志如下:
INFO 4840 --- [ main] c.s.demo.test.DemoApplicationTests : count = 1000
最后的结果是 1000,分布式锁生效。
Redisson突破了Redis数据结构维度的限制,通过一个特殊引用对象的帮助,Redisson允许以任意的组合方式构建多维度的复杂对象结构,实现了对象之间的类似传统数据库里的关联关系。使用范例如下:
- RMap<RSet<RList>, RList<RMap>> map = redisson.getMap("myMap");
- RSet<RList> set = redisson.getSet("mySet");
- RList<RMap> list = redisson.getList("myList");
-
- map.put(set, list);
- // 在特殊引用对象的帮助下,我们甚至可以构建一个循环引用,这是通过普通序列化方式实现不了的。
- set.add(list);
- list.add(map);
可能您已经注意到了,在map包含的元素发生改变以后,我们无需再次“保存/持久”这些对象。因为map对象所记录的并不是序列化以后的值,而是元素对象的引用。这让Redisson提供的对象在使用方法上,与普通Java对象的使用方法一致。从而让Redis成为内存的一部分,而不仅仅是一个储存空间。
以上范例中,一共创建了三个Redis数据结构:一个Redis HASH,一个Redis SET和一个Redis LIST。
多个连续命令可以通过RBatch对象在一次网络会话请求里合并发送,这样省去了产生多个请求消耗的时间和资源。这在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();
- }
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();
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。