当前位置: 首页 > news >正文

续期的无限套娃

scheduleExpirationRenewal最终会调用renewExpiration

private void renewExpiration() { // 这里的 1/3 是硬编码的规则 // 默认 lockWatchdogTimeout 是 30000ms // 所以每 10000ms 执行一次 Timeout task = commandExecutor.getConnectionManager().newTimeout(new TimerTask() { @Override public void run(Timeout timeout) throws Exception { // 执行 Lua 脚本,把 ttl 重新刷回 30秒 RFuture<Boolean> future = renewExpirationAsync(threadId); future.onComplete((res, e) -> { if (res) { // 如果续期成功,这就形成了递归调用:自己调自己 renewExpiration(); } }); } }, internalLockLeaseTime / 3, TimeUnit.MILLISECONDS); }

核心逻辑总结

  1. 三分之一原则:每隔锁超时时间的 1/3(默认10秒),检查一次。
  2. 无限递归:只要检查到锁还在,就重置过期时间,并注册下一次检查。
  3. 生死绑定:这个任务跑在客户端进程里,如果客户端宕机,任务停止,Redis 里的锁在 30秒 后自动过期。

四、我在生产环境踩过的坑:避坑实战

API 谁都会调,但能避开坑的才是老司机。这六个坑,都是真金白银换来的教训。

💣 陷阱一:好心办坏事 —— 弄死看门狗

这是新手最容易犯的错。

❌ 错误姿势

// 我怕死锁,所以强行指定 10秒 过期 lock.lock(10, TimeUnit.SECONDS); // 或者 lock.tryLock(1, 10, TimeUnit.SECONDS);

⚠️ 后果
Redisson 的看门狗(WatchDog)机制只有在你未指定锁过期时间时才会生效!
一旦你手动传了leaseTime,Redisson 就会认为你有自己的想法,不再插手。如果你的业务因为数据库卡顿跑了 15秒,第 10秒 时锁就会强制过期,其他线程长驱直入,爆发并发事故。

✅ 正确姿势
除非你非常确定业务能在指定时间内跑完,否则尽量不要传 leaseTime,让看门狗帮你自动续期

💣 陷阱二:锁粒度太粗 —— 全服暂停键

❌ 错误姿势

// 所有订单共用一把锁 RLock lock = redisson.getLock("LOCK_ORDER");

⚠️ 后果
这相当于把高速公路封成了独木桥。不管有多少个用户下单,同一时间只能处理一个。性能直接归零。

✅ 正确姿势
锁的粒度越细越好。只锁那个具体产生竞争的资源 ID。

// 只锁这个订单 RLock lock = redisson.getLock("order:pay:" + orderId);

💣 陷阱三:解锁的艺术 —— 谁加的锁谁来解

❌ 错误姿势

try { // 业务逻辑 } finally { lock.unlock(); // 直接解锁 }

⚠️ 后果

  1. 如果业务执行超时,锁已经被自动释放了,你再去unlock会抛出IllegalMonitorStateException
  2. 如果不小心解了别人的锁(虽然 Redisson 有 ID 校验防止误删,但异常处理依然重要)。

✅ 正确姿势

if (lock.isLocked() && lock.isHeldByCurrentThread()) { lock.unlock(); }

💣 陷阱四:重入锁的"递归噩梦"

Redisson 的锁虽然是可重入的(Reentrant),但如果你在递归或嵌套调用中不注意,很容易逻辑混乱。

❌ 风险代码

void methodA() { lock.lock(); try { methodB(); // methodB 里又 lock 了一次 } finally { lock.unlock(); // 只解了一层 } }

⚠️ 后果
Redis 里的锁计数器(Counter)如果不归零,锁是不会释放的。确保你的加锁次数和解锁次数严格匹配

💣 陷阱五:主从切换的"幽灵锁"

这是 Redis 架构天生的短板。

  1. Client A 在Master节点拿到了锁。
  2. Master 还没来得及把锁同步给 Slave,就宕机了。
  3. Slave 升级为新的 Master。
  4. Client B 来加锁,发现新 Master 上没锁,于是也加锁成功

⚠️ 后果
A 和 B 同时持有了锁。
解法:如果你不能容忍这个概率(极低),请看下文的 RedLock,或者转投 Zookeeper。对于 99% 的业务,我们选择接受这个风险。


五、RedLock 的爱恨情仇

有些面试官特别喜欢问 RedLock,但在实际工作中,它是一个让人爱恨交加的存在。

1. 它是为了解决什么?

解决 Redis 主从集群在 Failover(故障转移)时可能丢锁的问题。

2. 怎么用?

你需要准备3个或5个完全独立的 Redis 实例(不是 Cluster,不是 Sentinel,就是干干净净的单实例)。

RLock lock1 = redissonInstance1.getLock("lock"); RLock lock2 = redissonInstance2.getLock("lock"); RLock lock3 = redissonInstance3.getLock("lock"); // 创建红锁 RedissonRedLock lock = new RedissonRedLock(lock1, lock2, lock3); try { // 同时向 3个 Redis 申请锁 // 只要有 > 1.5个 (即2个) 申请成功,就算赢 lock.lock(); // 业务逻辑 } finally { lock.unlock(); }

3. 灵魂拷问:值得吗?

http://www.jsqmd.com/news/1098566/

相关文章:

  • YOLO实例分割工业圆形仪表指针读数识别数据集|电力电表电流电压表深度学习视觉实战仓库
  • 从零手写一个 mini-harness——看懂 agent 会干活的底层
  • 终极指南:如何在Audacity中安装OpenVINO AI音频插件
  • Claude Code 深度解析:从安装排错到项目级 AI 编程协作实战
  • 06.28.每日总结
  • 安全组网前五品牌推荐
  • 3分钟搞定抖音评论采集:从手动复制到自动化分析的终极免费方案
  • 导师放养没人带?笔墨 AI 全程逻辑引导,相当于半个指导老师
  • OntoX:本体论应用的“可运行/可视化”数字孪生平台(AI基于本体自动生成数字孪生页面)
  • 基于HarmonyOS 7.0 跨端开发的木工手作DIY页面实战
  • Go语言的sync.Cond系统通知
  • 2026年6月28日 主流Coding Plan平台全面对比|智谱、MiniMax、DeepSeek、GLM-5.2、Kimi-K2.7、字节方舟促销
  • 告别通讯黑盒:手把手教你用Python脚本抓取欧姆龙CP系列PLC数据(FINS/TCP协议详解)
  • 基于Basler相机的同步软件触发二次开发程序
  • APK Installer深度解析:Windows平台上的Android应用部署技术内幕
  • Java中的final 和 C++中 _
  • Stable Diffusion 图像生成原理浅析
  • 别再手动调间距了!用enumitem宏包5分钟搞定LaTeX列表排版
  • 从OpenBMC到商业部署:手把手带你走一遍飞腾腾珑E2000 BMC固件的完整适配流程
  • ppt模板_0133_蓝色波线
  • 数据分析入门实战:Excel、SQL、Python与BI工具全流程指南
  • Java的java.lang.StackWalker分布式
  • 别再手动算功率了!用Simulink搭建一个实时功率分析仪(附模型下载)
  • 怎样轻松掌握开源内存检测工具:Memtest86+新手实战完全手册
  • 紧急预警:传统人工Code Review正面临AI工具降维打击——错过这波升级,技术债将指数级膨胀
  • 3分钟快速上手:用HunterPie打造你的智能狩猎仪表盘
  • 如何免费高效查看.brd文件?OpenBoardView开源PCB查看器终极指南
  • 华为光猫配置解密工具:打开网络设备的加密黑匣子
  • 2026国内GEO公司排名前十深度盘点!行业格局+实力拆解(企业选型必看)
  • LangGraph 中的 add_messages