核心数据协调

分布式锁

确保同一时间只有一个 worker 运行某项任务,锁会自动过期,并且只能由其持有者安全释放。

条命令获取
1
条命令安全释放
1
个 Lua 脚本
0
步骤 1 / 5
Worker A 获取锁

NX 只在无人持有时才获取。PX 30000 让锁在 A 宕机时于 30 秒后过期。

示例会话playing
# Worker A 获取锁
hotkv> SET lock:billing-run tok-a81f NX PX 30000
OK

使用真实 HotKV 命令和示例回复的动画演示。点击任意步骤即可跳转。 命令和回复保持英文,与您在 HotKV 中输入和看到的完全一致。

问题所在

多台机器上的 cron 任务、支付扣款和缓存重建都不能同时运行两次。没有过期时间的锁会在持有者崩溃后被永远占用,而用普通的 DEL 释放锁,可能在您的锁过期之后删掉别人的锁。

HotKV 如何解决

带 NX 和 PX 的 SET 只在无人持有时获取锁,并为它设置过期时间,崩溃的持有者无法永远占用。每个持有者把一个随机令牌存为值。DELEX 配合 IFEQ 只在锁仍然保存着您的令牌时才删除它,这就是过去需要 Lua 脚本才能实现的安全释放。

逐步演示

逐条命令,看看发生了什么

  1. 01

    Worker A 获取锁

    NX 只在无人持有时才获取。PX 30000 让锁在 A 宕机时于 30 秒后过期。

    SET lock:billing-run tok-a81f NX PX 30000
  2. 02

    Worker B 被挡回

    锁已被持有,因此 B 得到 nil,并跳过这一轮。

    SET lock:billing-run tok-b22c NX PX 30000
  3. 03

    A 执行工作

    只有一个 worker 运行账单任务。

    PTTL lock:billing-run
  4. 04

    只释放自己的锁

    DELEX 只在值仍是 A 的令牌时才删除该键。

    DELEX lock:billing-run IFEQ tok-a81f
  5. 05

    令牌不对则什么也不做

    如果 A 太慢,而 B 现在持有锁,A 的释放操作不会动 B 的锁。

    DELEX lock:billing-run IFEQ tok-stale
适用场景

真实场景

定时任务

同一个 cron 在每个实例上运行,锁确保其中恰好只有一个实例执行工作。

支付

同一订单上的扣款和退款操作被串行化,绝不会重叠。

缓存击穿防护

只有一个请求重建开销大的缓存条目,其他请求等待或返回旧值。

内置功能

您将获得

带过期时间的获取

SET NX PX 只在锁空闲时获取,并带有超时。

SETNXPX

安全释放

DELEX IFEQ 只在值与您的令牌匹配时才删除。

DELEX

工作期间延长

检查剩余时间,并为长任务延长过期时间。

PTTLPEXPIRE

按摘要比较

对于大的值,DELEX IFDEQ 比较摘要而不是完整的值。

DIGESTIFDEQ

常见问题

为什么不直接 DEL 锁?

如果您的锁已经过期,并被另一个 worker 获取,普通的 DEL 会删掉对方的锁。DELEX IFEQ 只在锁仍然保存着您的令牌时才删除它。

过期时间应该设多长?

比任务通常所需的时间更长。对于长任务,在仍持有锁期间定期延长过期时间。

安全释放需要 Lua 吗?

不需要。DELEX 用一条命令完成比较和删除。

相关用例

在您自己的工作负载上试试

HotKV 兼容 Redis 协议,您可以把现有客户端指向它,运行这些相同的命令。