本期内容为自己总结归档,7天学会Redis。其中本人遇到过的面试问题会重点标记。
(若有任何疑问,可在评论区告诉我,看到就回复)
Day 7 - 一篇讲清楚Redisson 框架
7.1 什么是Redisson,核心定位
⭐Redisson概述
Redisson是一个基于Redis的Java驻内存数据网格(In-Memory Data Grid)客户端,它不仅提供了对Redis基本操作的封装,更重要的是提供了一系列分布式Java对象和服务的实现。Redisson让Java开发者能够在分布式环境中使用类似于Java SE的API。
官方定义:Redisson是架设在Redis基础上的一个Java驻内存数据网格,提供了分布式和可扩展的Java数据结构。
核心定位
Redisson的核心定位可以从四个维度理解:
1. 分布式Java对象
Redisson提供了与Java标准库接口一致的分布式对象,这些对象的数据存储在Redis中,可以被多个JVM实例共享访问。
2. 分布式服务
实现了Java并发包(java.util.concurrent)中的接口,提供分布式版本的锁、信号量、计数器等并发工具。
3. Redis高级客户端
除了基本的Redis命令支持,Redisson还提供了高级功能如连接池管理、负载均衡、故障转移等。
4. 企业级集成框架
与Spring、Spring Boot、Tomcat等主流框架深度集成,提供开箱即用的解决方案。
Redisson vs 原生Redis客户端
| 特性 | 原生Redis客户端(Jedis/Lettuce) | Redisson |
|---|---|---|
| API抽象级别 | 低级别,直接操作Redis命令 | 高级别,面向对象API |
| 分布式对象 | 需要自己实现 | 内置完整实现 |
| 并发工具 | 需要基于Redis命令封装 | 内置分布式锁、信号量等 |
| 连接管理 | 基础连接池 | 智能连接池,支持负载均衡 |
| 序列化 | 需要自己处理 | 内置多种序列化方案 |
| 学习曲线 | 简单直接 | 需要学习新API,但更符合Java习惯 |
| 适用场景 | 简单缓存、基础数据结构 | 复杂分布式系统、需要分布式协调 |
7.2 Redisson主要功能模块
7.2.1 分布式集合框架
Redisson的分布式集合完全实现了Java集合框架的接口,让开发者可以无缝迁移代码到分布式环境。
RMap - 分布式Map
java
// 创建分布式Map
RMap<String, User> map = redisson.getMap("userMap");
// 操作与HashMap完全一致
map.put("user1", new User("张三", 25));
User user = map.get("user1");
map.remove("user1");
// 分布式特性:支持跨JVM的监听器
map.addListener(new EntryCreatedListener<String, User>() {
@Override
public void onCreated(EntryEvent<String, User> event) {
System.out.println("Map条目被创建: " + event.getKey());
}
});
RList - 分布式List
java
RList<String> list = redisson.getList("myList");
list.add("item1");
list.add("item2");
String item = list.get(0);
list.remove(0);
其他分布式集合
-
RSet:分布式Set,支持交集、并集、差集操作
-
RQueue:分布式队列,支持阻塞获取
-
RDeque:分布式双端队列
-
RSortedSet:分布式有序Set
-
RScoredSortedSet:分布式带分数排序Set
7.2.2 分布式锁
⭐RLock - 分布式可重入锁
java
RLock lock = redisson.getLock("myLock");
// 尝试加锁,最多等待100秒,上锁后10秒自动解锁
boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
if (res) {
try {
// 执行业务逻辑
// 支持可重入:同一线程可重复获取锁
lock.lock(); // 再次获取,重入次数+1
// ...
} finally {
lock.unlock(); // 释放一次,重入次数-1
lock.unlock(); // 完全释放锁
}
}
⭐看门狗机制

关键设计决策:
-
续期间隔 :
TTL/3(默认 30 秒锁,10 秒检查一次),平衡 CPU 开销与安全性 -
续期失败 :业务线程崩溃,看门狗线程随之终止,锁自动过期,不会死锁
-
手动指定 TTL :若
lock.lock(10, TimeUnit.SECONDS),不启动看门狗,由业务保证执行时间
⭐RedLock 红锁

争议与生产建议:
-
Martin Kleppmann 批评:时钟跳跃、GC 停顿可能导致多个客户端同时持有锁
-
Redis 作者回应 :RedLock 在正确配置 NTP 、避免 GC 过长场景下可用
-
生产建议 :不推荐 在 CAP 强一致性场景使用(金融、支付),推荐 在允许极低概率失效场景使用(订单、库存)
7.2.3 分布式对象服务
RBucket - 分布式对象存储
java
RBucket<User> bucket = redisson.getBucket("userBucket");
bucket.set(new User("李四", 30), 1, TimeUnit.HOURS); // 设置1小时过期
User user = bucket.get();
// 支持原子操作
bucket.compareAndSet(oldUser, newUser);
其他对象服务
-
RTopic:分布式发布订阅
-
RHyperLogLog:分布式基数统计
-
RBloomFilter:分布式布隆过滤器
-
RBitSet:分布式位图
7.2.4 高级数据结构和算法
Redisson的延迟队列
java
RBlockingQueue<String> queue = redisson.getBlockingQueue("myQueue");
RDelayedQueue<String> delayedQueue = redisson.getDelayedQueue(queue);
// 延迟10秒将元素放入队列
delayedQueue.offer("task1", 10, TimeUnit.SECONDS);
// 在另一个线程中消费
String task = queue.take(); // 阻塞直到有元素可用
分布式限流器
java
RRateLimiter rateLimiter = redisson.getRateLimiter("myRateLimiter");
// 每1秒产生2个令牌
rateLimiter.trySetRate(RateType.OVERALL, 2, 1, RateIntervalUnit.SECONDS);
if (rateLimiter.tryAcquire()) {
// 获取到令牌,执行业务
}
7.2.5 分布式执行服务
Redisson提供了分布式执行服务,可以在多个节点上执行任务。
java
// 获取执行服务
RExecutorService executor = redisson.getExecutorService("myExecutor");
// 提交任务
Future<String> future = executor.submit(new CallableTask());
String result = future.get();
// 定义任务
public class CallableTask implements Callable<String>, Serializable {
@Override
public String call() throws Exception {
// 任务逻辑
return "任务完成";
}
}
7.3 ⭐Redisson使用场景
7.3.1 分布式锁场景
场景1:防止重复订单提交
java
@Service
public class OrderService {
@Autowired
private RedissonClient redisson;
public String createOrder(String orderId, String userId) {
String lockKey = "order:lock:" + orderId;
RLock lock = redisson.getLock(lockKey);
try {
// 尝试获取锁,5秒内获取不到则返回false
if (lock.tryLock(5, 30, TimeUnit.SECONDS)) {
// 检查订单是否已存在
if (checkOrderExists(orderId)) {
return "订单已存在";
}
// 创建订单逻辑
return doCreateOrder(orderId, userId);
} else {
return "系统繁忙,请稍后重试";
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return "系统异常";
} finally {
if (lock.isLocked() && lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
}
场景2:秒杀库存扣减
java
public class SeckillService {
public boolean seckill(String productId, String userId) {
String lockKey = "seckill:lock:" + productId;
RLock lock = redisson.getLock(lockKey);
try {
// 使用公平锁,保证先到先得
RLock fairLock = redisson.getFairLock(lockKey);
if (fairLock.tryLock(10, 60, TimeUnit.SECONDS)) {
try {
// 检查库存
int stock = getStock(productId);
if (stock <= 0) {
return false;
}
// 扣减库存
boolean success = decreaseStock(productId);
if (success) {
// 创建订单
createOrder(productId, userId);
return true;
}
} finally {
fairLock.unlock();
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return false;
}
}
7.3.2 分布式集合场景
场景:分布式Session共享
java
@Configuration
public class SessionConfig {
@Bean
public MapSessionRepository sessionRepository(RedissonClient redisson) {
// 使用RMap存储Session
return new RedissonSessionRepository(redisson);
}
public class RedissonSessionRepository {
private final RMap<String, Session> sessionMap;
public RedissonSessionRepository(RedissonClient redisson) {
this.sessionMap = redisson.getMap("sessions");
}
public void save(Session session) {
sessionMap.put(session.getId(), session);
}
public Session findById(String id) {
return sessionMap.get(id);
}
public void deleteById(String id) {
sessionMap.remove(id);
}
}
}
7.3.3 分布式任务调度场景
场景:延迟任务处理
java
@Component
public class DelayTaskProcessor {
@Autowired
private RedissonClient redisson;
@PostConstruct
public void init() {
// 创建延迟队列
RBlockingQueue<String> queue = redisson.getBlockingQueue("delay:queue");
RDelayedQueue<String> delayedQueue = redisson.getDelayedQueue(queue);
// 启动消费线程
new Thread(() -> {
while (true) {
try {
String task = queue.take();
processDelayTask(task);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}).start();
}
public void submitDelayTask(String taskId, long delay, TimeUnit unit) {
RDelayedQueue<String> delayedQueue = redisson.getDelayedQueue(
redisson.getBlockingQueue("delay:queue")
);
delayedQueue.offer(taskId, delay, unit);
}
private void processDelayTask(String taskId) {
// 处理延迟任务,如订单超时取消、定时提醒等
System.out.println("处理延迟任务: " + taskId);
}
}
7.3.4 分布式限流场景
场景:API限流保护
java
@RestController
public class ApiController {
@Autowired
private RedissonClient redisson;
@GetMapping("/api/resource")
public ResponseEntity<?> getResource(@RequestParam String apiKey) {
String limiterKey = "api:limit:" + apiKey;
RRateLimiter limiter = redisson.getRateLimiter(limiterKey);
// 设置限流规则:每秒最多10个请求
limiter.trySetRate(RateType.OVERALL, 10, 1, RateIntervalUnit.SECONDS);
if (limiter.tryAcquire()) {
// 执行业务逻辑
return ResponseEntity.ok(getResourceData());
} else {
return ResponseEntity.status(429).body("请求过于频繁,请稍后重试");
}
}
}
7.3.5 分布式数据一致性场景
场景:读写锁保证数据一致性
java
@Service
public class InventoryService {
@Autowired
private RedissonClient redisson;
private RReadWriteLock readWriteLock;
@PostConstruct
public void init() {
readWriteLock = redisson.getReadWriteLock("inventory:lock");
}
// 读取库存(多个读锁可以同时持有)
public int getInventory(String productId) {
RLock readLock = readWriteLock.readLock();
try {
readLock.lock();
// 读取库存数据
return readFromCacheOrDB(productId);
} finally {
readLock.unlock();
}
}
// 更新库存(写锁排他)
public boolean updateInventory(String productId, int delta) {
RLock writeLock = readWriteLock.writeLock();
try {
writeLock.lock();
// 更新库存数据
return doUpdateInventory(productId, delta);
} finally {
writeLock.unlock();
}
}
}
7.4 Redisson架构原理深度解析
7.4.1 连接管理与负载均衡
Redisson使用Netty作为网络通信框架,支持多种连接管理模式:

连接池配置
java
Config config = new Config();
config.useSingleServer()
.setAddress("redis://127.0.0.1:6379")
.setConnectionPoolSize(64) // 最大连接数
.setConnectionMinimumIdleSize(10) // 最小空闲连接数
.setConnectTimeout(10000) // 连接超时时间
.setTimeout(3000) // 命令超时时间
.setRetryAttempts(3) // 重试次数
.setRetryInterval(1500); // 重试间隔
7.4.2 序列化机制
Redisson支持多种序列化方案,可根据业务需求选择:
java
Config config = new Config();
// 1. Jackson序列化(推荐)
config.setCodec(new JsonJacksonCodec());
// 2. FST序列化(高性能)
config.setCodec(new FstCodec());
// 3. Kryo序列化(性能好,但需要注册类)
KryoCodec kryoCodec = new KryoCodec();
kryoCodec.registerClass(User.class);
config.setCodec(kryoCodec);
// 4. 自定义序列化
config.setCodec(new SerializationCodec() {
@Override
protected ObjectDecoder createValueDecoder(ClassLoader classLoader) {
return new CustomDecoder();
}
@Override
protected ObjectEncoder createValueEncoder() {
return new CustomEncoder();
}
});
7.4.3 发布订阅机制
Redisson使用Redis的Pub/Sub功能实现事件通知:
java
// 发布者
RTopic topic = redisson.getTopic("myTopic");
topic.publish(new Message("Hello, World!"));
// 订阅者
topic.addListener(Message.class, (channel, msg) -> {
System.out.println("收到消息: " + msg);
});
// 分布式锁释放通知的实现
public class LockPubSub extends PublishSubscribe<LockMessage> {
@Override
protected LockMessage decode(ByteBuf buf, Codec codec) {
// 解码锁消息
return codec.getValueDecoder().decode(buf, null);
}
@Override
protected void onMessage(LockMessage message) {
// 处理锁释放通知
if (message instanceof LockReleasedMessage) {
// 通知等待锁的线程
notifyLockReleased();
}
}
}
7.4.5 Redisson分布式锁知识体系

7.5 Redisson与Spring生态集成
7.5.1 Spring Boot自动配置
bash
# application.yml
spring:
redis:
redisson:
config: |
singleServerConfig:
address: "redis://127.0.0.1:6379"
password: null
database: 0
connectionPoolSize: 64
connectionMinimumIdleSize: 10
subscriptionConnectionPoolSize: 50
dnsMonitoringInterval: 5000
codec: !<org.redisson.codec.JsonJacksonCodec> {}
threads: 16
nettyThreads: 32
7.5.2 Spring Cache集成
java
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager cacheManager(RedissonClient redissonClient) {
Map<String, CacheConfig> config = new HashMap<>();
// 配置用户缓存
config.put("userCache", new CacheConfig(
30 * 60 * 1000, // 30分钟过期
1000 // 最大缓存数量
));
return new RedissonSpringCacheManager(redissonClient, config);
}
}
@Service
public class UserService {
@Cacheable(value = "userCache", key = "#userId")
public User getUser(String userId) {
// 数据库查询
return userRepository.findById(userId);
}
@CachePut(value = "userCache", key = "#user.id")
public User updateUser(User user) {
// 更新数据库
return userRepository.save(user);
}
@CacheEvict(value = "userCache", key = "#userId")
public void deleteUser(String userId) {
userRepository.deleteById(userId);
}
}
7.5.3 Spring Session集成
java
@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800)
public class SessionConfig {
@Bean
public RedissonConnectionFactory redissonConnectionFactory(
RedissonClient redisson) {
return new RedissonConnectionFactory(redisson);
}
@Bean
public HttpSessionIdResolver httpSessionIdResolver() {
// 使用Cookie和Header双重方式传递Session ID
return new HeaderHttpSessionIdResolver("X-Auth-Token");
}
}
7.6 ⭐面试高频考点
考点1:⭐Redisson分布式锁的实现原理?
面试回答:
Redisson分布式锁的实现基于Redis的Hash数据结构和Lua脚本,核心原理包括:
-
可重入机制:使用Hash结构存储锁信息,key为锁名称,field为客户端标识(UUID + threadId),value为重入次数。同一线程可重复获取锁,每次获取重入次数加1。
-
看门狗自动续期:获取锁成功后,启动后台线程(看门狗)定期(默认10秒)检查锁是否仍被持有,如果是则重置过期时间为30秒,防止业务执行时间过长导致锁过期。
-
Lua脚本保证原子性:所有锁操作(加锁、解锁、续期)都使用Lua脚本执行,确保原子性,避免竞态条件。
-
公平锁实现:通过Redis的List结构维护等待队列,结合发布订阅机制通知等待的客户端,实现先到先得的公平锁。
-
解锁安全:解锁时检查客户端标识,确保只有加锁的客户端才能解锁,避免误解锁。
加锁Lua脚本关键逻辑:
lua
-- 如果锁不存在,创建锁并设置重入次数为1
-- 如果锁已存在且是同一客户端,重入次数加1
-- 如果锁被其他客户端持有,返回锁的剩余生存时间
考点2:Redisson与Jedis、Lettuce的区别?
面试回答:
| 特性 | Jedis | Lettuce | Redisson |
|---|---|---|---|
| API级别 | 低级别,Redis命令封装 | 低级别,响应式支持 | 高级别,分布式对象抽象 |
| 连接管理 | 连接池,阻塞I/O | 单连接多路复用,非阻塞I/O | 连接池,基于Netty的非阻塞I/O |
| 线程安全 | 非线程安全,需用连接池 | 线程安全,连接可共享 | 线程安全,内置连接管理 |
| 分布式支持 | 无,需自己实现 | 无,需自己实现 | 内置分布式锁、集合、服务等 |
| 序列化 | 需要自己处理 | 需要自己处理 | 内置多种序列化方案 |
| 适用场景 | 简单同步操作 | 高并发,响应式编程 | 复杂分布式系统,需要分布式协调 |
| 学习成本 | 低 | 中 | 较高(需要学习新API) |
核心区别:Jedis和Lettuce是Redis客户端,主要提供Redis命令操作;Redisson是基于Redis的分布式服务框架,提供了更高层次的抽象和分布式原语。
考点3:⭐Redisson的看门狗机制如何工作?
面试回答:
Redisson的看门狗(Watchdog)机制是防止分布式锁过期的重要保障,工作流程如下:
-
触发时机 :当使用
lock()方法获取锁时(未指定leaseTime参数),看门狗机制会自动启用。 -
续期逻辑:
-
获取锁成功后,启动一个后台定时任务
-
默认每10秒(锁超时时间的1/3)执行一次续期检查
-
检查锁是否还被当前线程持有,如果是则将锁过期时间重置为30秒
-
-
自动停止:
-
锁被正常释放时,看门狗任务会自动取消
-
客户端宕机时,看门狗任务随进程终止,锁最终会因超时自动释放
-
-
配置参数:
java
Config config = new Config(); config.setLockWatchdogTimeout(30000); // 设置看门狗超时时间,默认30秒
注意事项:
-
使用
tryLock(leaseTime, unit)指定租约时间时,看门狗不会启动 -
看门狗机制增加了Redis的负载,需合理设置超时时间
-
网络分区时可能造成锁被多个客户端持有,需结合业务处理