【大白话说Java面试题 第173题】【07_Redis篇】第9题:使用过 Redisson 嘛?说说它的原理?

发布时间:2026/10/30 18:59:28

【大白话说Java面试题 第173题】【07_Redis篇】第9题:使用过 Redisson 嘛?说说它的原理? 第9题使用过 Redisson 嘛说说它的原理回答核心考点Redisson是 Java 生态中最成熟的 Redis 分布式锁实现大厂面试不会只问用过没有而是深入考察底层数据结构Hash 结构、Pub/Sub 频道、看门狗续期的 Netty 定时任务实现、可重入锁的 Lua 脚本原子逻辑、公平锁与非公平锁的队列差异以及MultiLock 与 Redlock 的架构区别。面试官真正想判断的是你是否阅读过 Redisson 源码能否从使用层面深入到原理层面并准确区分 Redisson 各组件的适用边界。1. Redisson 整体架构1.1 核心组件组件职责关键类RedissonClient客户端入口管理连接池RedissonConnectionManager管理 Redis 连接NettyMasterSlaveConnectionManagerCommandExecutor执行 Redis 命令同步/异步CommandAsyncExecutorRLock分布式锁接口RedissonLockRFuture异步结果封装RedissonPromise1.2 与 Redis 的交互方式Redisson 基于Netty实现 NIO 网络通信所有 Redis 命令通过异步管道发送支持连接池复用和自动重连。Java 业务线程 → RLock API → CommandExecutor → Netty Channel → Redis Server ↓ 异步回调RFuture← 结果解析 ← 响应返回2. 可重入锁实现原理Hash 结构2.1 数据结构Redisson 使用 RedisHash结构存储锁信息而非简单 String# 锁的 Redis 结构HGETALL lock:order:1001# 返回# 1) UUID:ThreadID # field 线程唯一标识# 2) 3 # value 重入次数字段说明Key锁名如lock:order:1001FieldUUID:ThreadID格式为Redisson 实例 ID 线程 IDValue重入次数hincrby原子增减2.2 加锁 Lua 脚本源码级-- RedissonLock.tryLockInnerAsync 的核心脚本if(redis.call(exists,KEYS[1])0)then-- 锁不存在首次加锁redis.call(hincrby,KEYS[1],ARGV[2],1);redis.call(pexpire,KEYS[1],ARGV[1]);returnnil;-- 返回 nil 表示获取成功end;if(redis.call(hexists,KEYS[1],ARGV[2])1)then-- 锁存在且是当前线程持有重入redis.call(hincrby,KEYS[1],ARGV[2],1);redis.call(pexpire,KEYS[1],ARGV[1]);returnnil;end;-- 锁被其他线程持有返回剩余过期时间毫秒returnredis.call(pttl,KEYS[1]);参数值说明KEYS[1]lock:order:1001锁名ARGV[1]30000过期时间毫秒ARGV[2]UUID:ThreadID线程唯一标识2.3 解锁 Lua 脚本源码级-- RedissonLock.unlockInnerAsync 的核心脚本if(redis.call(hexists,KEYS[1],ARGV[3])0)then-- 不是当前线程持有的锁返回 nil解锁失败returnnil;end;localcounterredis.call(hincrby,KEYS[1],ARGV[3],-1);if(counter0)then-- 仍持有锁重入次数 0续期并返回 0redis.call(pexpire,KEYS[1],ARGV[2]);return0;else-- 完全释放删除锁并发布解锁通知redis.call(del,KEYS[1]);redis.call(publish,KEYS[2],ARGV[1]);return1;end;参数值说明KEYS[1]lock:order:1001锁名KEYS[2]redisson_lock__channel:{lock:order:1001}解锁通知频道ARGV[1]0解锁消息内容ARGV[2]30000过期时间毫秒ARGV[3]UUID:ThreadID线程唯一标识2.4 可重入流程示例RLocklockredissonClient.getLock(order:1001);lock.lock();// Hash: { UUID:ThreadID: 1 }, pttl30000mslock.lock();// Hash: { UUID:ThreadID: 2 }, pttl30000ms重入lock.lock();// Hash: { UUID:ThreadID: 3 }, pttl30000ms重入lock.unlock();// Hash: { UUID:ThreadID: 2 }, pttl30000mslock.unlock();// Hash: { UUID:ThreadID: 1 }, pttl30000mslock.unlock();// DEL lock:order:1001 PUBLISH 解锁通知3. 看门狗Watchdog自动续期机制3.1 为什么需要看门狗业务执行时间不确定如 Full GC、慢查询固定过期时间可能导致锁提前释放。看门狗在锁持有期间自动续期直到业务完成。3.2 核心参数参数默认值说明lockWatchdogTimeout30000ms锁看门狗超时时间锁的过期时间续期周期10000mslockWatchdogTimeout / 3每 10 秒检查一次续期目标30000ms每次续期恢复到lockWatchdogTimeout3.3 续期 Lua 脚本-- 看门狗续期脚本if(redis.call(hexists,KEYS[1],ARGV[2])1)thenredis.call(pexpire,KEYS[1],ARGV[1]);return1;end;return0;3.4 看门狗启动与停止条件条件行为说明lock()不指定 leaseTime启动看门狗默认行为自动续期lock(10, TimeUnit.SECONDS)不启动看门狗显式指定过期时间10 秒后强制释放unlock()调用成功停止看门狗取消定时任务业务线程中断停止看门狗线程死亡不再续期3.5 底层实现Netty HashedWheelTimer// Redisson 看门狗定时任务简化源码逻辑privatevoidscheduleExpirationRenewal(longthreadId){// 使用 Netty 的时间轮定时器TimeouttaskcommandExecutor.getConnectionManager().newTimeout(timeout-{// 异步续期RFutureBooleanfuturerenewExpirationAsync(threadId);future.onComplete((res,e)-{if(e!null){// 续期异常重新调度scheduleExpirationRenewal(threadId);return;}if(res){// 续期成功递归调度下一次scheduleExpirationRenewal(threadId);}});},internalLockLeaseTime/3,// 延迟 10 秒执行TimeUnit.MILLISECONDS);// 将任务存入 Map解锁时取消expirationRenewalMap.put(getEntryName(),task);}关键设计时间轮定时器Netty 的HashedWheelTimer相比ScheduledThreadPoolExecutor性能更高适合高频定时任务异步续期续期操作通过异步命令发送不阻塞业务线程递归调度每次续期成功后递归调度下一次续期形成永续续期任务取消解锁时从expirationRenewalMap取出任务并取消停止续期。4. 阻塞重试机制Pub/Sub 事件驱动4.1 为什么不用自旋简单的while循环自旋会导致 CPU 空转。Redisson 通过Pub/Sub 订阅解锁通知实现事件驱动的阻塞重试无 CPU 浪费。4.2 核心流程// RedissonLock.tryLock 的阻塞重试逻辑简化publicbooleantryLock(longwaitTime,longleaseTime,TimeUnitunit){longdeadlineSystem.currentTimeMillis()unit.toMillis(waitTime);// 1. 首次尝试获取锁LongttltryAcquire(leaseTime,unit,threadId);if(ttlnull)returntrue;// 获取成功// 2. 计算剩余等待时间longremainingdeadline-System.currentTimeMillis();if(remaining0)returnfalse;// 3. 订阅解锁通知频道// 频道名redisson_lock__channel:{lock:order:1001}RFutureRedissonLockEntrysubscribeFuturesubscribe(threadId);// 4. 阻塞等待解锁通知或超时if(!subscribeFuture.await(remaining,TimeUnit.MILLISECONDS)){returnfalse;// 等待超时}// 5. 收到通知后循环重试while(remaining0){ttltryAcquire(leaseTime,unit,threadId);if(ttlnull)returntrue;// 获取成功remainingdeadline-System.currentTimeMillis();if(remaining0)returnfalse;// 等待锁释放通知或 ttl 过期getEntry(threadId).getLatch().tryAcquire(ttl,TimeUnit.MILLISECONDS);}returnfalse;}4.3 Pub/Sub 频道设计频道名用途消息内容redisson_lock__channel:{lockName}解锁通知0固定值redisson_lock__channel:{lockName}:1公平锁等待队列通知等待线程的排序信息关键设计每个锁对应一个独立的 Pub/Sub 频道解锁时通过PUBLISH广播通知所有等待线程被唤醒后竞争锁。5. 公平锁与非公平锁5.1 非公平锁默认RedissonLock默认实现获取锁时不考虑等待顺序所有线程公平竞争。优点吞吐量大无队列维护开销。缺点可能导致某些线程长期饥饿一直抢不到锁。5.2 公平锁RedissonFairLock按请求锁的顺序获取先请求的线程优先获得锁。RLockfairLockredissonClient.getFairLock(order:1001);fairLock.lock();// 公平锁实现原理每个请求锁的线程在 Redis 中创建一个等待队列节点ZSet 或 List解锁时按照队列顺序通知下一个等待线程被通知的线程获取锁其他线程继续等待。对比维度非公平锁公平锁吞吐量高低队列维护开销饥饿风险存在不存在实现复杂度低高需维护等待队列适用场景大多数场景需要严格顺序保证的场景6. 主从一致性方案MultiLock 与 Redlock6.1 MultiLock联锁要求所有指定的 Redis 节点都加锁成功才算获取锁成功。RLocklock1redissonClient1.getLock(order:1001);RLocklock2redissonClient2.getLock(order:1001);RLocklock3redissonClient3.getLock(order:1001);RLockmultiLockredissonClient.getMultiLock(lock1,lock2,lock3);multiLock.lock();// 三个节点全部加锁成功才生效特点可靠性最高所有节点都有锁但可用性最低任一节点故障即加锁失败。6.2 Redlock红锁要求多数派N/2 1节点加锁成功且总耗时小于锁过期时间。ConfigconfignewConfig();config.useRedLock(newRedissonClientConfig(redis://node1:6379),newRedissonClientConfig(redis://node2:6379),newRedissonClientConfig(redis://node3:6379));RedissonClientredissonRedisson.create(config);RLockredLockredisson.getRedLock(order:1001);redLock.lock();特点平衡可靠性和可用性容忍部分节点故障。6.3 MultiLock vs Redlock 对比维度MultiLockRedlock成功条件所有节点加锁成功多数派节点加锁成功可靠性极高所有节点有锁高多数派有锁可用性低任一节点故障即失败中容忍少数节点故障适用场景极端强一致、节点数少高可用要求、节点数多7. Redisson 其他分布式组件组件功能底层实现RMap分布式 MapRedis HashRSet分布式 SetRedis SetRList分布式 ListRedis ListRQueue分布式队列Redis List/StreamRDelayedQueue延迟队列Redis ZSet 定时任务RAtomicLong分布式原子计数Redis String LuaRCountDownLatch分布式倒计时门闩Redis String Pub/SubRPermitExpirableSemaphore分布式信号量Redis String ZSetRBucket分布式对象存储Redis String8. 生产环境避坑指南8.1 锁的过期时间必须大于业务最大执行时间如果业务执行时间不确定使用lock()启用看门狗而非lock(10, TimeUnit.SECONDS)。8.2 避免锁粒度过粗getLock(global)会导致所有操作串行。应按业务 ID 细粒度加锁。8.3 注意看门狗的续期上限看门狗默认无限续期如果业务线程死循环或阻塞锁将永远不被释放。建议业务逻辑设置超时熔断监控锁的持有时间超过阈值如 60 秒强制告警并人工介入。8.4 公平锁的性能陷阱公平锁维护等待队列吞吐量显著低于非公平锁。除非业务严格要求顺序否则使用默认非公平锁。8.5 Redlock 的时钟同步要求使用 Redlock 时必须确保所有 Redis 节点时钟同步NTP否则锁过期时间计算会出错。8.6 连接池配置优化# Redisson 连接池配置singleServerConfig:connectionMinimumIdleSize:10connectionPoolSize:64idleConnectionTimeout:10000connectTimeout:10000timeout:3000retryAttempts:3retryInterval:15009. 面试官追问与高分回答模板追问 1“Redisson 分布式锁的原理是什么”低分回答“用 Hash 结构实现可重入看门狗续期Pub/Sub 重试。”没有源码级细节高分回答Redisson 分布式锁的核心原理分四层数据结构层使用 Redis Hash 结构存储锁field为UUID:ThreadIDvalue为重入次数。Lua 脚本原子执行hexists判断归属 →hincrby修改计数 →del完全释放。看门狗层基于 Netty 的HashedWheelTimer每 10 秒leaseTime/3异步执行 Lua 脚本续期将锁过期时间重置为 30 秒。业务完成或线程中断时取消定时任务。重试层首次获取失败后订阅redisson_lock__channel:{lockName}频道阻塞等待解锁通知Pub/Sub避免 CPU 空转。收到通知后循环重试直到超时。多节点层MultiLock 要求所有节点加锁成功Redlock 要求多数派成功解决主从一致性问题。生产环境必须直接使用 Redisson严禁手写 SETNX。追问 2“看门狗机制是怎么实现的如果业务线程挂了怎么办”高分回答看门狗基于 Netty 的HashedWheelTimer实现获取锁时如果调用lock()不指定 leaseTime启动定时任务延迟 10 秒后执行任务执行时通过 Lua 脚本检查锁是否仍被当前线程持有hexists如果是则pexpire续期到 30 秒续期成功后递归调度下一次续期任务形成永续续期解锁时从expirationRenewalMap取出任务并取消。如果业务线程挂了未调用 unlock看门狗会随线程死亡而停止续期因为定时任务引用在线程上下文中锁在 30 秒后自动释放不会永久死锁。但如果线程死循环或阻塞看门狗会持续续期导致锁永不释放这是需要监控告警的极端情况。追问 3“Redisson 的公平锁和非公平锁有什么区别”高分回答Redisson 默认使用非公平锁RedissonLock所有线程公平竞争吞吐量大但可能饥饿。公平锁RedissonFairLock按请求顺序分配锁每个请求锁的线程在 Redis 中创建一个等待队列节点通常用 ZSet 或 List 维护顺序解锁时按照队列顺序通过 Pub/Sub 通知下一个等待线程被通知的线程获取锁其他线程继续阻塞等待。公平锁消除了饥饿问题但维护队列的开销大吞吐量显著低于非公平锁。除非业务严格要求顺序如排队扣减库存否则使用默认非公平锁。追问 4“MultiLock 和 Redlock 有什么区别”高分回答两者都是 Redisson 解决多节点一致性的方案但成功条件和适用场景不同MultiLock联锁要求所有指定的 Redis 节点都加锁成功才算获取锁成功。可靠性极高所有节点都有锁但可用性低任一节点故障即失败。适合节点数少、极端强一致的场景。Redlock红锁要求多数派N/2 1节点加锁成功且总耗时小于锁过期时间。平衡了可靠性和可用性容忍部分节点故障。适合节点数多、高可用要求的场景。但 Redlock 存在理论争议Martin Kleppmann 论文时钟漂移、GC 停顿、无 fencing token。实际工程中在时钟同步、网络稳定的环境中足够可靠但极端场景应优先选择 ZooKeeper 或 etcd。追问 5“Redisson 除了分布式锁还用过哪些组件”高分回答Redisson 是一个完整的 Redis 分布式工具集除了分布式锁我还使用过RMap分布式 Map基于 Redis Hash支持本地缓存Near Cache和读写分离。RDelayedQueue延迟队列基于 Redis ZSet 存储延迟任务Redisson 后台线程定时扫描到期任务并转移到目标队列。用于订单超时取消、定时通知等场景。RAtomicLong分布式原子计数器基于 Redis String Lua 脚本实现 CAS 操作。RCountDownLatch分布式倒计时门闩基于 Redis String Pub/Sub 实现跨 JVM 的线程协调。RPermitExpirableSemaphore分布式信号量支持许可证过期自动释放用于限流场景。Redisson 的优势是将 Redis 原语封装为 Java 熟悉的并发工具接口降低使用门槛。追问 6“Redisson 连接 Redis 用的是阻塞 IO 还是非阻塞 IO”高分回答Redisson 基于Netty实现NIO 非阻塞 IO。所有 Redis 命令通过异步管道发送支持连接池复用和自动重连。具体特点异步命令RFuture封装异步结果支持回调和组合操作连接池维护最小空闲连接和最大连接数避免频繁创建销毁连接自动重连连接断开后自动重试对业务透明Pub/Sub 独立连接订阅操作使用独立连接避免阻塞普通命令通道。相比 Jedis 的阻塞 BIORedisson 的 NIO 在高并发下性能更高连接数更少。10. 方案选型速查表场景推荐方案说明通用分布式锁redissonClient.getLock()非公平锁吞吐量高默认启用看门狗需要严格顺序保证redissonClient.getFairLock()公平锁消除饥饿但吞吐量低多 Redis 节点高可用redissonClient.getRedLock()多数派机制容忍部分节点故障极端强一致所有节点redissonClient.getMultiLock()所有节点加锁成功可用性低业务执行时间不确定lock()不指定 leaseTime启用看门狗自动续期业务执行时间确定lock(leaseTime, unit)禁用看门狗固定过期时间延迟队列redissonClient.getDelayedQueue()基于 ZSet 实现用于定时任务分布式计数器redissonClient.getAtomicLong()基于 String LuaCAS 操作面试官想要的满分总结Redisson 是 Java 生态中最成熟的 Redis 分布式锁实现其核心价值在于将能用的分布式锁升级为生产级可靠的分布式锁。理解 Redisson 必须抓住四个底层机制Hash 可重入fieldUUID:ThreadID, value重入次数Lua 脚本原子执行判断、计数、释放看门狗续期NettyHashedWheelTimer每 10 秒异步续期解决业务超时释放问题Pub/Sub 重试订阅解锁频道事件驱动阻塞重试避免 CPU 空转多节点方案MultiLock全成功和 Redlock多数派解决主从一致性。生产环境必须注意锁粒度按业务 ID 细分、看门狗监控防止死循环续期、公平锁仅在严格顺序场景使用、Redlock 需确保时钟同步。最后记住Redisson 不仅是分布式锁框架更是完整的 Redis 分布式工具集RMap、RDelayedQueue、RAtomicLong 等选型时应充分利用其生态能力而非仅使用锁功能。觉得对您有帮助麻烦点点关注啦您的关注是我创作的最大动力~
延伸阅读

更多相关文章

2026/10/28 6:23:09

C++ STL核心组件解析:从容器算法到迭代器与实战避坑指南

1. 从“手搓轮子”到“开箱即用”:为什么每个C程序员都绕不开STL 如果你刚开始学C,可能还在和指针、内存管理、数组越界这些“坑”斗智斗勇。好不容易写了个链表或者排序算法,结果发现换个数据类型又要重写一遍,代码又长又容易出错…

2026/10/30 17:37:10

三菱Q系列与汇川AM系列 Modbus TCP 主从站配置与数据包解析实战

1. Modbus TCP通信基础与项目背景 在工业自动化领域,不同品牌PLC之间的数据交互一直是工程师面临的常见需求。三菱Q系列作为日系PLC的代表产品,与国产汇川AM系列的通信整合,往往需要依赖Modbus TCP这类标准化协议。我曾在一个汽车零部件生产线…

2026/10/30 18:56:10

【IEEE出版 | 高届数会议 | 马来西亚理工大学主办 | 广州线下主会场 + 线上参会可选】第八届国际科技创新学术交流大会暨第七届信息科学与教育国际学术会议(ICISE-IE 2026)

第八届国际科技创新学术交流大会暨第七届信息科学与教育国际学术会议(ICISE-IE 2026) 2026 8th International Academic Exchange Conference on Science and Technology Innovation&2026 7th International Conference on Information Science an…

2026/10/30 18:56:10

【经济学、管理学、人工智能、大数据、模型计算机相关交叉主题均为本届会议征稿范围 | 中国-广州】第八届国际科技创新学术交流大会暨经济管理与模型工程国际学术会议(ICEMME 2026)

第八届国际科技创新学术交流大会暨经济管理与模型工程国际学术会议(ICEMME 2026) The 8th International Conference on Economic Management and Model Engineering 随着全球化和信息化的不断深入,经济管理、模型工程之间的关系变得更加紧…

2026/10/30 18:56:10

龙格现象:采样点误差为零,插值曲线却给出了不可能的值

一、问题的提法:不比误差,比值域 用一条高次多项式精确穿过一排等间距的采样点,点越多,曲线在两端甩得越厉害。 这是龙格现象(Runges phenomenon)的一句话版本。但要把它变成一条能写进代码评审的判据,还差一步。 常见的讨论方式是「误差有多大」——误差 1.9 听起来…

2026/10/30 18:56:10

相机手感为什么总差一点:导数视角下的跟随、样条与弧长参数化

一、三个症状,同一个底层概念 先摆三个你大概率都遇到过的场景: 你给相机写了个跟随逻辑,在自己机器上试手感很好,交给同事试,对方说「有点飘」。你们俩跑的是同一份代码。 你给相机画了条样条路径让它平滑飞过,曲线画得很漂亮,跑起来相机却忽快忽慢。 你把路径上的控制…

2026/10/30 18:51:10

农业物联网与遥感技术在苗情灾情监控系统中的应用

1. 苗情灾情监控系统概述在现代农业生产中,及时掌握作物生长状况和灾害发生情况是提高农业生产效率的关键。苗情灾情监控系统通过整合物联网、遥感技术和数据分析手段,为农业生产者提供从田间到决策的全链条支持。这套系统能够实时监测作物生长参数、识别…

2026/10/29 17:05:52

全国计算机二级C语言真题PDF高效刷题指南

简介:这份PDF是全国计算机二级C语言考试的试题与答案解析,专为备考二级C语言的考生准备。内容涵盖C语言特点与设计理念、程序基本组成单位、main函数执行流程、函数嵌套调用规则、标识符命名规范、整型实型字符型数据类型、八进制十六进制数合法形式、运…

2026/10/29 17:06:02

requests+BeautifulSoup:爬虫抓取h1标题的入门实战指南

简介:一份以实战为导向的Python爬虫入门资源,面向具备基本编程基础、希望快速掌握网络数据抓取的初学者,可解决从零编写简单爬虫的常见困惑。实例以requests库发送HTTP请求、BeautifulSoup解析HTML文档,完整演示从网页中提取 标题…

2026/10/29 17:06:13

递推最小二乘参数辨识MATLAB编程:二阶系统与渐消记忆实现

简介:这是一篇面向控制系统、信号处理与机器学习等领域学习者的最小二乘参数辨识程序说明文档。资源共包含一个docx格式文档,压缩包大小七十八KB,内容围绕递推最小二乘算法和渐消记忆最小二乘算法展开:先构造一个极点位于单位圆内…

2026/10/30 0:00:46

NCP1342高频准谐振反激控制器:从设计约束到验收的完整方案

简介:NCP1342 高频准谐振反激控制器应用介绍译文文档,面向电源设计工程师、硬件研发人员及开关电源学习者,帮助读者跨越英文原版资料的语言门槛,系统理解这款高集成度 QR Flyback 控制器的设计要点。文档围绕芯片核心特性展开&…

2026/10/30 0:00:46

NCP1342准谐振反激电源设计:从选型到验收的全流程解析

简介:这份文档面向电源设计工程师与开关电源学习者,系统梳理NCP1342高频准谐振反激控制器的应用要点,帮助读者快速理解这款高集成度离线电源变换器控制芯片的工作机制与设计方法。内容涵盖芯片核心特性、引脚功能定义、电气特性参数表、最大额…

2026/10/30 0:00:46

Web系统自动登出机制设计与实现全解析

1. 系统自动登出机制的设计初衷在各类Web应用和后台管理系统中,自动登出功能早已成为标配。这个看似简单的功能背后,实际上涉及用户安全、资源管理和体验优化的多重考量。作为从业十多年的老开发,我见过太多因为登出逻辑设计不当导致的安全事…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑