分布式锁旨在解决分布式场景下多台机器对同一资源的竞争问题,确保在同一时刻只有一台机器能够获取并持有资源的访问权限。
Redis 的 setnx 命令(set if not exist)是实现分布式锁的基础操作。例如,执行setnx key value
,若 Redis 中不存在指定的 key,则创建该 key 并赋值为 value,同时返回 1,表示获取锁成功;若 key 已存在,则返回 0,表示获取锁失败。然而,这种简单实现存在明显缺陷,当获取锁的机器出现故障时,无法自动释放锁,将导致其他机器长时间等待,资源被长时间占用。
为应对机器故障导致锁无法释放的情况,引入了设置过期时间的机制。通过setnx key value nx ex 100
(其中时间单位为秒)命令,在创建锁的同时为其设定有效期。这样,即使持有锁的机器发生故障,锁也会在过期时间到达后自动释放,避免资源的永久阻塞。但这又引发了新的问题,如任务可能在锁过期时尚未完成,以及可能误释放其他机器持有的锁。
流程图源码
flowchart LR
A[业务开始] --> B[解析 @RedisLock 注解,提取必要参数]
B --> C{参数校验}
C -- 不合法 --> D[日志记录错误信息]
C -- 合法 --> E[1. 组装业务唯一键 uniqueBusinessKey<br>2. 设置 value: UUID]
E --> F{redisTemplate<br>#setIfAbsent<br> 尝试获取锁}
F -- 成功 --> G[redisTemplate#expire 设置超时时间]
F -- 失败 --> D
G --> H[组装 Task 属性到自定义任务队列中<br>进行“续锁”操作]
H --> I[执行切点方法pjp#process]
I --> J{是否异常}
J -- 是 --> K[Task 加入 clean 队列中,等待统一移除]
J -- 否 --> L[redisTemplate#delete 释放锁资源]
subgraph 定时任务 Daemon 每 2 秒执行一次
H --> M[remainExpireTime < lockTime/3*2?]
M -- 是 --> N[重新设置超时时间<br>redisTemplate#expire]
M -- 否 --> O[loop]
end
K --> L
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。