大家好!今天我要和大家聊聊 Redisson,一个在 Spring 开发中非常实用的分布式工具。如果你在微服务架构中遇到分布式锁、分布式缓存或者消息队列的难题,Redisson 可能就是你的救星!赶紧点赞收藏,关注我获取更多干货!
Redisson 是一个基于 Redis 的 Java 客户端,但它不仅仅是一个简单的客户端,而是一个功能强大的分布式工具箱。它把 Redis 的能力封装成了各种 Java 对象,比如分布式锁、分布式集合、消息队列等,让我们在开发中可以直接使用这些对象,而不用自己去实现复杂的分布式逻辑。
传统的 Redis 客户端(比如 Jedis)需要自己实现分布式锁、缓存等逻辑,而 Redisson 已经把这些功能封装好了。比如,用 Jedis 实现分布式锁需要处理锁的超时、续约等问题,而 Redisson 的 RLock
对象直接解决了这些问题。
<dependency>
<groupId>org.redissongroupId>
<artifactId>redissonartifactId>
<version>3.23.0version>
dependency>
<dependency>
<groupId>org.redissongroupId>
<artifactId>redisson-spring-boot-starterartifactId>
<version>3.23.0version>
dependency>
redisson:
single-server-config:
address: "redis://127.0.0.1:6379"
password: "your-password"
database: 0
thread-pool-size: 10
redisson:
cluster-server-config:
node-addresses:
- "redis://192.168.1.1:6379"
- "redis://192.168.1.2:6379"
- "redis://192.168.1.3:6379"
password: "your-password"
thread-pool-size: 10
redisson:
sentinel-server-config:
master-name: "mymaster"
node-addresses:
- "redis://192.168.1.1:26379"
- "redis://192.168.1.2:26379"
- "redis://192.168.1.3:26379"
password: "your-password"
thread-pool-size: 10
@Configuration
public class RedissonConfig {
@Bean
public RedissonClient redissonClient() {
Config config = new Config();
config.useSingleServer()
.setAddress("redis://127.0.0.1:6379")
.setPassword("your-password")
.setDatabase(0);
return Redisson.create(config);
}
}
Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
RedissonClient redisson = Redisson.create(config);
@Autowired
private RedissonClient redissonClient;
public void testReentrantLock() {
RLock lock = redissonClient.getLock("myLock");
try {
// 尝试获取锁,最多等待 10 秒,锁的超时时间为 30 秒
boolean isLocked = lock.tryLock(10, 30, TimeUnit.SECONDS);
if (isLocked) {
// 执行业务逻辑
System.out.println("锁获取成功,执行业务逻辑");
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
// 释放锁
lock.unlock();
System.out.println("锁已释放");
}
}
RFairLock fairLock = redissonClient.getFairLock("myFairLock");
try {
fairLock.lock();
// 执行业务逻辑
System.out.println("公平锁获取成功");
} finally {
fairLock.unlock();
}
RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("myReadWriteLock");
// 获取读锁
readWriteLock.readLock().lock();
try {
System.out.println("读锁获取成功");
// 执行读操作
} finally {
readWriteLock.readLock().unlock();
}
// 获取写锁
readWriteLock.writeLock().lock();
try {
System.out.println("写锁获取成功");
// 执行写操作
} finally {
readWriteLock.writeLock().unlock();
}
RRedLock redLock = new RRedLock(
redissonClient1.getLock("redLock"),
redissonClient2.getLock("redLock"),
redissonClient3.getLock("redLock")
);
try {
redLock.lock();
// 执行业务逻辑
System.out.println("红锁获取成功");
} finally {
redLock.unlock();
}
RSet<String> set = redissonClient.getSet("mySet");
set.add("value1");
set.add("value2");
set.add("value3");
System.out.println("集合大小:" + set.size());
System.out.println("集合内容:" + set);
RList<String> list = redissonClient.getList("myList");
list.add("item1");
list.add("item2");
list.add("item3");
System.out.println("列表大小:" + list.size());
System.out.println("列表内容:" + list);
RMap<String, String> map = redissonClient.getMap("myMap");
map.put("key1", "value1");
map.put("key2", "value2");
System.out.println("Map 大小:" + map.size());
System.out.println("Map 内容:" + map);
RQueue<String> queue = redissonClient.getQueue("myQueue");
queue.add("task1");
queue.add("task2");
queue.add("task3");
System.out.println("队列大小:" + queue.size());
System.out.println("队列内容:" + queue);
// 发布消息
RTopic topic = redissonClient.getTopic("myTopic");
topic.publish("Hello, Redisson!");
// 订阅消息
topic.addListener(String.class, (channel, msg) -> {
System.out.println("接收到消息:" + msg);
});
// 发布消息
RStream<String> stream = redissonClient.getStream("myStream");
stream.add("message1");
stream.add("message2");
// 订阅消息
Consumer<String> consumer = stream.addConsumer("group1", "consumer1");
List<StreamMessageId> messages = consumer.read(100);
for (StreamMessageId messageId : messages) {
String message = consumer.read(messageId);
System.out.println("接收到消息:" + message);
}
Redisson 的可重入锁通过 Redis 的 SET
命令实现,使用了 Lua 脚本确保原子性。每次获取锁时,Redisson 会在 Redis 中存储一个随机值,释放锁时会检查这个值是否匹配,确保只有锁的持有者才能释放锁。
Redisson 使用了一个后台线程(WatchDog)来自动续约锁。如果锁的超时时间快到了,WatchDog 会自动延长锁的超时时间,避免锁因为超时而丢失。
当锁被释放时,Redisson 会发送一个解锁消息到 Redis,通知其他等待的线程可以尝试获取锁。
公平锁通过维护一个等待队列来实现。当一个线程获取锁失败时,它会被加入到等待队列中。当锁被释放时,队列中的第一个线程会尝试获取锁。
Redisson 的消息队列基于 Redis 的 Pub/Sub 模式实现。RTopic
使用发布/订阅模式,RStream
使用 Redis 的 Stream 数据结构。
Redisson 使用 Lua 脚本确保操作的原子性,同时利用 Redis 的数据结构(比如 Sorted Set、List)来实现线程安全。
RLock lock1 = redissonClient1.getLock("lock1");
RLock lock2 = redissonClient2.getLock("lock2");
RMultiLock multiLock = new RMultiLock(lock1, lock2);
try {
multiLock.lock();
// 执行业务逻辑
} finally {
multiLock.unlock();
}
Redisson 使用 Lua 脚本和 WatchDog 机制确保锁的高可用性,即使 Redis 主节点宕机,从节点也能接管锁的管理。
RMapCache<String, String> mapCache = redissonClient.getMapCache("myMapCache");
mapCache.put("key1", "value1", 1, TimeUnit.MINUTES); // 设置过期时间为 1 分钟
Redisson 提供了缓存的自动同步机制,确保数据的一致性。
redisson:
thread-pool-size: 20
Redisson 自动管理连接池,确保连接的高效复用。
Redisson 提供了 readMode
配置,可以设置为 SLAVE
或 MASTER
,根据需求选择读取数据的节点。
Redisson 支持自动故障转移,当主节点宕机时,会自动切换到从节点。
尽量设置合理的超时时间,避免锁一直无法释放。
lock.tryLock(10, 30, TimeUnit.SECONDS); // 最多等待 10 秒,锁的超时时间为 30 秒
超时时间应该根据业务逻辑的执行时间来设置,避免过长或过短。
使用 Redisson 的分布式集合时,确保所有操作都通过 Redisson 提供的 API 进行,避免直接操作 Redis 数据。
可以适当增加线程池的大小,提高并发处理能力。
在微服务架构中,可以使用 Redisson 的分布式锁来协调多个服务的并发操作。
使用 Redisson 的消息队列可以确保消息的可靠传递,避免消息丢失。
希望这篇博客能帮助大家更好地理解和使用 Redisson!如果有任何问题,欢迎在评论区留言,我会第一时间回复大家!别忘了点赞收藏,关注我获取更多技术干货! ❤️❤️❤️