分布式锁竞争激烈如何监控?
简化版
监控锁竞争不能只看获取失败次数,要同时看申请量、成功率、等待分位数、持锁时长、续期与超时,并按 lock key、业务和实例定位热点。告警最终应关联业务吞吐与错误率,区分正常互斥、持锁者变慢和重试风暴。
详细版
客户端为每次 acquire 记录等待时间和结果原因,为成功请求记录 hold duration、续期次数及释放结果;锁服务侧观察排队长度、活跃租约、过期回收、存储延迟和 top key。Trace 中给出 key 的哈希、owner、attempt 和 fencing token,但不要泄露完整业务标识。
诊断顺序是:先确认流量是否增长,再看竞争是否集中于少数 key,然后判断持锁时间变长还是失败重试变密。用 Little’s Law 粗估排队,用基线与 SLO 设置分位数告警,并对高基数标签做 top-K、分桶或采样,避免观测系统自身被打爆。
完整版教学
一、先区分竞争与故障
多人申请同一把锁不一定异常,秒杀库存或单任务 leader 本来就会竞争。真正需要告警的是等待时间突破业务预算、持锁时长异常增长、超时后形成重试放大,或竞争从预期 key 扩散到大量资源。指标必须能回答“谁在等、等谁、为什么变慢”。
记忆钩子:申请量说明有多忙,等待时间说明有多堵,持锁时间说明堵点在谁。
二、客户端需要记录哪些指标
每次获取应按 success/timeout/error/cancel 分类计数,并记录 acquire latency 的 P50、P95、P99。获取成功后记录持锁时长、续期次数、释放失败和租约剩余量;失败请求还要记录退避轮数。只统计平均值会把少数长等待隐藏掉。
lock_acquire_total{result}
lock_acquire_duration_seconds histogram
lock_hold_duration_seconds histogram
lock_renew_total{result}
lock_release_total{result}
三、锁服务侧怎样看热点
服务端要观察活跃租约数、等待队列长度、授予速率、过期回收数、后端存储延迟和 leader 切换。热点 key 不宜直接作为指标标签,否则百万订单号会制造高基数;可使用 top-K 日志、哈希前缀和 exemplar 关联具体 Trace。
| 信号 | 常见含义 | 下一步 |
|---|---|---|
| 等待升高、持锁稳定 | 请求量增长 | 查热点与容量 |
| 持锁 P99 升高 | 临界区或下游变慢 | 查 owner Trace |
| 超时和重试同时升高 | 重试风暴 | 限制预算 |
| 过期回收升高 | 进程暂停或续期失败 | 查 GC/网络 |
四、用数字判断是否已经排队
Little’s Law 只能在统计窗口近似稳态时粗估:平均等待数 Lq ≈ 有效到达率 λ × 平均排队时间 Wq。例如同一 key 稳定完成 40 QPS、平均排队 0.25 秒,队列平均约有 10 个请求。另一个过载场景中,临界区平均 20ms,单 key 理论能力约 50 QPS;若持续输入 80 QPS,系统不再是稳态,积压会以约 30 个/秒增长,不能再用一个固定平均等待数描述。
单 key 理论吞吐 ≈ 1 / 平均持锁秒数
竞争率 = 发生等待的申请数 / 总申请数
超时率 = acquire_timeout / acquire_total
五、Trace 与日志怎样串起因果
在 span 中记录 lock namespace、脱敏 key hash、owner、等待时长、租期、attempt 和 token。获取 span 应作为临界区 span 的父节点,这样能直接看到锁内哪个数据库或 RPC 拉长持锁。日志使用同一个 traceId,并对超时、续期失败和长持锁事件全量保留。
完整 key 可能包含用户或订单信息,不应进入通用标签。排障需要反查时,可由受控系统把 hash 映射回资源,保留权限与审计。
六、告警与处置怎样设计
告警应以业务影响为主、内部信号为辅,例如获取 P99 超过 300ms 且订单成功率下降持续 5 分钟。单次抢锁失败通常是正常控制流,不宜逐条报警。处置先限制重试、缩短锁内慢操作或隔离热点,再决定扩容、拆 key 或改用队列串行。
发布前建立正常时段与峰值基线;仪表盘同时展示 QPS、竞争率、等待、持锁、错误、续期、业务吞吐和 top key,避免跨多个页面猜因果。
七、常见误区与追问
- 误区:获取失败率高就代表锁服务故障。 tryLock 失败可能是业务预期,需结合等待和业务结果判断。
- 误区:平均等待时间足够。 少量长尾就能耗尽线程池,必须关注 P95/P99 与最大值。
- 误区:把 lock key 直接放进指标标签。 高基数会显著增加监控成本甚至拖垮系统。
- 误区:增加锁服务节点能解决单 key 热点。 同一资源的互斥上限由临界区时长决定。
- 追问:怎样找到谁持锁太久? 用 owner 与 traceId 关联临界区 Trace,定位其中的慢调用。
- 追问:阈值怎么定? 从业务延迟预算、正常基线和线程池容量反推,而非套统一数字。
- 追问:竞争突然上升先做什么? 控制重试并确认热点 key,先阻止排队继续放大。
八、加强记忆
锁竞争观测沿“申请—等待—持有—续期—释放”全生命周期布点,再把客户端、锁服务与业务 SLO 串起来。用分位数看长尾、用 top-K 找热点、用 Trace 找持锁慢点、用重试预算防放大;这样才能区分流量增长、临界区变慢和锁基础设施故障。