上一篇
想象一下,双11零点刚过,你的秒杀系统正在处理海量订单,某个订单的业务逻辑需要15秒完成,但你设置的Redis锁过期时间只有10秒 😱,结果第11秒时锁自动释放,另一个请求拿到了相同的锁,导致同一个商品被重复售卖... 这就是典型的锁提前失效问题!
// 典型的问题代码示例 Boolean locked = redisTemplate.opsForValue().setIfAbsent("lock:order_123", "1", 10, TimeUnit.SECONDS); if(locked) { try { // 假设这个业务需要15秒... processOrder(); // ⚠️ 第11秒锁就失效了! } finally { redisTemplate.delete("lock:order_123"); } }
Redis分布式锁通常通过SET key value NX EX
实现,但面临两个核心问题:
方案 | 实现难度 | 可靠性 | 适用场景 |
---|---|---|---|
简单TTL延长 | 低并发短任务 | ||
看门狗线程 | 中长耗时任务 | ||
Redisson自动续期 | 生产环境首选 | ||
Lua脚本续期 | 需要精确控制的场景 |
public boolean renewLock(String lockKey, String requestId, int expireTime) { // 只有锁仍属于当前客户端时才续期 if(requestId.equals(redisTemplate.opsForValue().get(lockKey))) { redisTemplate.expire(lockKey, expireTime, TimeUnit.SECONDS); return true; } return false; } // 使用示例 new Thread(() -> { while(locked) { try { Thread.sleep(5000); // 每5秒续期一次 renewLock("lock:order_123", "client_1", 10); } catch (Exception e) { break; } } }).start();
Redisson的解决方案最优雅:
RLock lock = redisson.getLock("orderLock"); try { // 看门狗默认30秒过期,每10秒自动续期 lock.lock(); processOrder(); } finally { lock.unlock(); }
它的秘密在于:
(lockTimeout / 3)
时间检查一次 -- KEYS[1] 锁key -- ARGV[1] 客户端ID -- ARGV[2] 新的过期时间(ms) if redis.call("GET", KEYS[1]) == ARGV[1] then return redis.call("PEXPIRE", KEYS[1], ARGV[2]) else return 0 end
Java调用示例:
String script = "...上面的Lua脚本..."; redisTemplate.execute( new DefaultRedisScript<>(script, Long.class), Collections.singletonList("lock:order_123"), "client_1", "15000" );
// 业务层双重检查示例 if(!checkLockOwnership(lockKey, myId)) { throw new RuntimeException("锁已丢失,终止操作"); }
SET lock_key NX EX 10
,导致任何客户端都能解锁 通过合理的续期机制,你的Redis锁就能像永动机一样可靠运转啦!🎉 没有完美的分布式锁,只有适合业务场景的锁方案。
本文由 帅烨霖 于2025-08-05发表在【云服务器提供商】,文中图片由(帅烨霖)上传,本平台仅提供信息存储服务;作者观点、意见不代表本站立场,如有侵权,请联系我们删除;若有图片侵权,请您准备原始证明材料和公证书后联系我方删除!
本文链接:https://vps.7tqx.com/wenda/545866.html
发表评论