77 lines
8.1 KiB
JSON
77 lines
8.1 KiB
JSON
{
|
||
"topic": "distributed-lock",
|
||
"type": "short_answer",
|
||
"schema_version": "1.0.0",
|
||
"generated": "2026-09-09T21:42:00+08:00",
|
||
"questions": [
|
||
{
|
||
"id": "sa-001",
|
||
"type": "short_answer",
|
||
"difficulty": 3,
|
||
"tags": [
|
||
"distributed-lock",
|
||
"lock-design"
|
||
],
|
||
"question": "请解释 RedisLockUtil 中 DEFAULT_LOCK_TIMEOUT(10秒)和 DEFAULT_ACQUIRE_TIMEOUT(3秒)两个参数的区别,以及它们分别在什么场景下需要调整。",
|
||
"answer": "DEFAULT_LOCK_TIMEOUT(10秒)是锁的持有时间上限,即 Redis key 的 TTL。业务必须在此时间内完成操作,否则锁自动释放,可能导致并发问题。如果业务逻辑执行时间较长(如涉及远程调用、大量数据处理),需要适当增大该值。DEFAULT_ACQUIRE_TIMEOUT(3秒)是等待获取锁的最长时间,即客户端自旋等待的上限。在高并发场景下,如果多个客户端竞争同一把锁,超过此时间未获取到就返回失败。如果希望提高请求成功率而非快速失败,可以增大该值,但会增加线程阻塞时间。",
|
||
"keywords": [
|
||
"锁持有时间",
|
||
"TTL",
|
||
"锁等待时间",
|
||
"acquireTimeout",
|
||
"业务执行时间",
|
||
"高并发",
|
||
"自旋等待"
|
||
],
|
||
"scoring_rubric": "满分(5分):准确区分两个超时的含义(1分),说明 lockTimeout 是锁 TTL 自动释放(1分),说明 acquireTimeout 是自旋等待上限(1分),各给出一个调整场景(1分),区分概念清晰无混淆(1分)。混淆两者含义扣3分,只回答一个扣2分。",
|
||
"explanation": "DEFAULT_LOCK_TIMEOUT(10秒)是锁的持有时间上限,即 Redis key 的 TTL。业务必须在此时间内完成操作,否则锁自动释放,可能导致并发问题。如果业务逻辑执行时间较长(如涉及远程调用、大量数据处理),需要适当增大该值。DEFAULT_ACQUIRE_TIMEOUT(3秒)是等待获取锁的最长时间,即客户端自旋等待的上限。在高并发场景下,如果多个客户端竞争同一把锁,超过此时间未获取到就返回失败。如果希望提高请求成功率而非快速失败,可以增大该值,但会增加线程阻塞时间。"
|
||
},
|
||
{
|
||
"id": "sa-002",
|
||
"type": "short_answer",
|
||
"difficulty": 4,
|
||
"tags": [
|
||
"distributed-lock",
|
||
"redis-lock"
|
||
],
|
||
"question": "RedisLockUtil 使用 setIfAbsent(SET NX)实现锁的获取。请解释该方案的\"安全性\"(Safety)和\"活性\"(Liveness)分别由什么保证,以及各自的局限是什么。",
|
||
"answer": "安全性(Safety)——互斥性保证:由 Redis 的 SET NX 原子操作保证。NX 参数确保只有当 key 不存在时才能设置成功,从而保证同一时刻最多只有一个客户端持有锁。局限:在 Redis 主从架构下,主节点写入锁后未同步到从节点就宕机,从节点提升为主后锁丢失,安全性被破坏。活性(Liveness)——最终可获取性保证:由锁的 TTL(lockTimeout)自动过期保证。即使持有锁的客户端崩溃或网络分区,锁最终会过期释放,其他客户端可以获取。局限:如果业务执行时间超过 TTL,锁提前释放,安全性又被打破(活性的保证反而威胁了安全性)。这是一个经典的两难困境,也是 Redisson 引入看门狗(watchdog)自动续期机制的原因。",
|
||
"keywords": [
|
||
"SET NX原子操作",
|
||
"互斥性",
|
||
"主从同步",
|
||
"TTL自动过期",
|
||
"锁续期",
|
||
"watchdog",
|
||
"活性与安全性的权衡"
|
||
],
|
||
"scoring_rubric": "满分(5分):准确解释安全性由 SET NX 保证(1分),说明主从架构下的局限(1分),准确解释活性由 TTL 保证(1分),说明业务超时与安全性的矛盾(1分),提及看门狗/续期机制作为解决方案(1分)。仅回答一半内容扣2分,概念错误扣3分。",
|
||
"explanation": "安全性(Safety)——互斥性保证:由 Redis 的 SET NX 原子操作保证。NX 参数确保只有当 key 不存在时才能设置成功,从而保证同一时刻最多只有一个客户端持有锁。局限:在 Redis 主从架构下,主节点写入锁后未同步到从节点就宕机,从节点提升为主后锁丢失,安全性被破坏。活性(Liveness)——最终可获取性保证:由锁的 TTL(lockTimeout)自动过期保证。即使持有锁的客户端崩溃或网络分区,锁最终会过期释放,其他客户端可以获取。局限:如果业务执行时间超过 TTL,锁提前释放,安全性又被打破(活性的保证反而威胁了安全性)。这是一个经典的两难困境,也是 Redisson 引入看门狗(watchdog)自动续期机制的原因。"
|
||
},
|
||
{
|
||
"id": "sa-003",
|
||
"type": "short_answer",
|
||
"difficulty": 5,
|
||
"tags": [
|
||
"distributed-lock",
|
||
"lock-design"
|
||
],
|
||
"question": "如果要将 RedisLockUtil 升级为支持看门狗自动续期和可重入的生产级分布式锁,需要做哪些改造?请从架构设计角度列出至少三项关键改造点并简述实现思路。",
|
||
"answer": "1. 看门狗自动续期(Watchdog):在后台启动一个定时任务(如每 lockTimeout/3 时间),检查当前线程是否仍持有锁,如果持有则续期(重新 SET EX)。Redisson 的做法是在获取锁成功后启动一个 Netty 时间轮,定时续期,锁释放时取消定时器。2. 可重入锁支持:当前实现不支持可重入。改造思路是用 Hash 结构存储锁信息(field=锁持有者标识,value=重入次数),获取锁时如果已是持有者则 incr 重入计数,解锁时 decr,计数归零才真正删除 key。Lua 脚本需要相应改造以支持重入逻辑。3. 看门狗参数可配置化:当前的 lockTimeout 硬编码为 10 秒,应支持自定义续期间隔、最大续期时间等参数,以适配不同业务场景。4. 公平锁支持:当前实现是非公平锁(先到不一定先得),可引入 Redis 有序集合(Sorted Set)实现 FIFO 队列,按请求时间戳排序获取锁。5. 线程安全优化:移除 ThreadLocal 存储 lockValue 的设计,改为将 lockValue 作为 tryLock 的返回值传递给 unlock,避免线程池复用导致的 lockValue 错乱问题。",
|
||
"keywords": [
|
||
"看门狗watchdog",
|
||
"自动续期",
|
||
"可重入锁",
|
||
"Hash结构",
|
||
"重入计数",
|
||
"Lua脚本改造",
|
||
"公平锁",
|
||
"Sorted Set",
|
||
"参数可配置",
|
||
"ThreadLocal替代"
|
||
],
|
||
"scoring_rubric": "满分(5分):列出至少三项改造点(1分),每项有实现思路描述(每项1分,共3分),至少一项提到 Redisson 作为参考实现(0.5分),回答逻辑清晰、无概念错误(0.5分)。只列改造点无实现思路扣2分,概念错误(如说可重入用 List 实现)扣2分。",
|
||
"explanation": "1. 看门狗自动续期(Watchdog):在后台启动一个定时任务(如每 lockTimeout/3 时间),检查当前线程是否仍持有锁,如果持有则续期(重新 SET EX)。Redisson 的做法是在获取锁成功后启动一个 Netty 时间轮,定时续期,锁释放时取消定时器。2. 可重入锁支持:当前实现不支持可重入。改造思路是用 Hash 结构存储锁信息(field=锁持有者标识,value=重入次数),获取锁时如果已是持有者则 incr 重入计数,解锁时 decr,计数归零才真正删除 key。Lua 脚本需要相应改造以支持重入逻辑。3. 看门狗参数可配置化:当前的 lockTimeout 硬编码为 10 秒,应支持自定义续期间隔、最大续期时间等参数,以适配不同业务场景。4. 公平锁支持:当前实现是非公平锁(先到不一定先得),可引入 Redis 有序集合(Sorted Set)实现 FIFO 队列,按请求时间戳排序获取锁。5. 线程安全优化:移除 ThreadLocal 存储 lockValue 的设计,改为将 lockValue 作为 tryLock 的返回值传递给 unlock,避免线程池复用导致的 lockValue 错乱问题。"
|
||
}
|
||
]
|
||
} |