Redis分布式锁怎么实现?Redisson看门狗机制是什么?

2025年 阅读约 10 分钟 面试指南 · Redis面试

Redis分布式锁实现与Redisson看门狗机制详解,包含可重入锁、红锁及最佳实践。

一句话总结

Redis分布式锁推荐SET key value NX EX原子操作实现,释放时用Lua脚本校验value。Redisson看门狗自动续期防止锁提前释放。可重入锁用Hash结构记录持有次数。

初级理解

基础实现:

# 错误做法:SETNX + EXPIRE 分两步,非原子操作 SETNX lock_key 1 EXPIRE lock_key 30 # 正确做法:一条命令原子加锁 SET lock_key 1 NX EX 30

释放锁:

# Lua脚本校验value后再删除,防止误删他人锁 if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end
一句话总结:SET NX EX原子加锁 + Lua脚本校验释放。

中级深入

Redisson看门狗机制:

• 自动续期:调用lock()不指定过期时间时,默认30秒 • 定时续期:每隔10秒(30/3)检查锁是否仍被持有,是则重置为30秒 • 作用:防止业务未完成时锁过期释放

可重入锁:

Redisson使用Hash结构:key -> {threadId: count} 同一线程重入时count+1,释放时count-1,为0时才真正删除
注意:Redisson看门狗只在未指定过期时间时生效。指定了过期时间,看门狗不会续期。

高级拓展

红锁(RedLock):

# 针对Redis主从切换导致锁丢失的问题 1. 向N个独立Redis节点同时加锁 2. 超过半数成功才算加锁成功 3. 锁的有效时间 = 过期时间 - 获取锁的时间 # 争议:增加了复杂性,一般场景慎用

Redisson vs Jedis:

Redisson分布式锁示例: RLock lock = redissonClient.getLock("myLock"); if (lock.tryLock(3, 30, TimeUnit.SECONDS)) { // 执行业务逻辑 } lock.unlock();
面试加分项:能说出Redisson看门狗原理、可重入锁实现、红锁争议,说明你对Redis分布式锁有深入理解。

实战场景

场景:Redisson分布式锁实战

// 订单超时未支付自动取消 @Scheduled(fixedRate = 60000) public void cancelExpiredOrders() { List orders = orderMapper.selectExpiredOrders(LocalDateTime.now().minusMinutes(30)); for (Order order : orders) { RLock lock = redissonClient.getLock("order:cancel:" + order.getId()); try { if (lock.tryLock(5, 10, TimeUnit.SECONDS)) { Order current = orderMapper.selectById(order.getId()); if ("PENDING".equals(current.getStatus())) { orderMapper.updateStatus(order.getId(), "PENDING", "CANCELLED"); stockService.releaseStock(order.getProductId(), order.getQuantity()); } } } finally { if (lock.isHeldByCurrentThread()) lock.unlock(); } } }

面试模拟

Q:Redisson看门狗是如何实现自动续期的?

A:1. 调用lock()不指定过期时间时,默认30秒;2. 后台定时任务每隔10秒检查锁是否仍被持有;3. 如果仍被持有,重置过期时间为30秒;4. 线程释放锁或宕机后,定时任务停止,锁30秒后自动释放。

Q:Redis分布式锁为什么要用Lua脚本释放?

A:因为GET和DEL是两个操作,如果分开执行,在GET和DEL之间锁可能已过期,其他线程已获取锁,此时DEL会误删其他线程的锁。Lua脚本可以保证GET+DEL的原子性,先校验value再删除。