分布式任务锁
分布式任务锁:Redis 实现,获取锁/释放锁,防止订单重复扣款与消息重复发送
分布式任务锁:传入锁 key,获取锁、释放锁;防止重复执行任务。
基于 Redis SET NX 实现,多台服务器共用同一把锁。
典型场景:订单防重复扣款、消息防重复发送、定时任务防并发执行。
获取锁成功返回 token,业务完成后须用同一 token 释放锁。
基于 Redis SET NX 实现,多台服务器共用同一把锁。
典型场景:订单防重复扣款、消息防重复发送、定时任务防并发执行。
获取锁成功返回 token,业务完成后须用同一 token 释放锁。
调用地址:https://api.ynlskj.com.cn/gateway/distlock
请求方法:POST
在其他地方怎么调用
- 请求地址用上面的调用地址,把 JSON 放在请求体里
- 方法用
POST - API Key 只能放在请求头
X-API-Key,不要写进网址,也不要写进 Query 框 - Key 在「个人中心 → API Key」里复制,登录后会自动填入你自己的 Key
参数说明
| 参数 | 位置 | 必填 | 说明 |
|---|---|---|---|
key | Body JSON | 是 | 锁标识,如 order:pay:123、msg:notify:456 |
action | Body JSON | 否 | acquire 获取锁(默认)、release 释放锁、extend 续期、status 查询是否被占用 |
ttl | Body JSON | 否 | 锁过期秒数,默认 30,最大 86400。获取锁与续期时使用 |
token | Body JSON | 释放/续期时必填 | 获取锁成功时返回的凭证,防止误释放别人的锁 |
namespace | Body JSON | 否 | 命名空间,用于同一账号下隔离不同业务线 |
X-API-Key | Header | 是 | 你的 API Key |
这个接口是干什么的?
把「分布式锁」做成远程 API。业务在执行关键操作之前先调本接口尝试获取锁,只有 acquired=true 才继续执行;完成后用返回的 token 释放锁,避免同一订单重复扣款、消息重复发送、定时任务并发跑两次。
适合小微团队不想自建 Redis 锁代码:支付回调、消息通知、库存扣减、对账脚本等,都可以远程调一次完成加锁判断。
典型使用流程
- 收到业务请求(如支付成功回调、待发送通知)
- 先调本接口:
key=order:pay:订单号,ttl=30 - 看返回:
acquired=true且记下token,再执行业务;false则说明已有实例在处理,直接跳过 - 业务结束:调
action=release带上同一key与token释放锁
适用场景
| 场景 | key 示例 | 建议 ttl |
|---|---|---|
| 订单防重复扣款 | order:pay:20240823001 | 30–60 秒 |
| 消息防重复发送 | msg:notify:用户ID | 60 秒 |
| 定时任务防并发 | job:daily_report | 300 秒 |
| 库存扣减 | stock:sku_1001 | 10–30 秒 |
| 对账 / 导出脚本 | export:merchant_5 | 600 秒 |
请求示例
| 场景 | Body 示例 |
|---|---|
| 获取锁 | {"action":"acquire","key":"order:pay:10086","ttl":30} |
| 释放锁 | {"action":"release","key":"order:pay:10086","token":"返回的token"} |
| 续期(长任务) | {"action":"extend","key":"job:daily_report","token":"...","ttl":120} |
| 查询是否被占用 | {"action":"status","key":"order:pay:10086"} |
业务侧代码示例(伪代码)
resp = POST /gateway/distlock {"action":"acquire","key":"order:pay:"+orderId,"ttl":30}
if (!resp.data.acquired) {
return "已有实例在处理,跳过"
}
token = resp.data.token
try {
// 执行业务:扣款、发消息等
} finally {
POST /gateway/distlock {"action":"release","key":"order:pay:"+orderId,"token":token}
}
说明与限制
- 基于 Redis SET NX + Lua 安全释放,多台服务器共用同一把锁
- 锁带
ttl自动过期,防止进程崩溃导致死锁;长任务请用extend续期 - 释放锁必须携带获取时返回的
token,不能释放他人持有的锁 - 每个 API Key 账号下的
key相互隔离;可用namespace再分子业务
返回说明
| 字段 | 说明 |
|---|---|
ret | ok 成功,err 失败 |
data.acquired | 核心字段:获取锁时 true 表示成功,false 表示锁已被占用 |
data.token | 获取锁成功时的凭证,释放/续期时必须原样传回 |
data.released | 释放锁是否成功(token 不匹配时为 false) |
data.extended | 续期是否成功 |
data.held | 查询状态时:锁是否被占用 |
data.ttl / expire_at | 剩余秒数 / 过期 Unix 时间戳 |
data.retry_after | 获取锁失败时,建议等待秒数(等于当前锁剩余 ttl) |
msg | 本站提示,如「次数充足,剩余 99 次」或「次数不足,剩余 0 次」 |
remain_quota | 本次调用后的剩余次数 |
可直接复制的代码
未登录时示例只显示「你的密钥」。登录后会自动填入你自己的 Key,不会展示别人的。
<?php
$ch = curl_init('https://api.ynlskj.com.cn/gateway/distlock');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['X-API-Key: 你的密钥', 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => '{
"action": "acquire",
"key": "order:pay:10086",
"ttl": 30
}',
]);
echo curl_exec($ch);
请求参数演示
{"action":"acquire","key":"order:pay:10086","ttl":30}
响应演示
{"ret":"ok","data":{"action":"acquire","key":"order:pay:10086","acquired":true,"token":"a1b2c3d4e5f6789012345678abcdef01","ttl":30,"expire_at":1735689630}}