vault backup: 2026-05-24 21:18:14
This commit is contained in:
+18
-7
@@ -97,20 +97,28 @@ return 0 -- 被其他客户端持有
|
||||
```
|
||||
|
||||
```go
|
||||
// Go 调用
|
||||
// Go 调用——与上方 Lua 脚本等价的分布式锁实现
|
||||
script := redis.NewScript(`
|
||||
if redis.call("get", KEYS[1]) == false then
|
||||
-- setex(key, seconds, value): ARGV[1]=过期秒数, ARGV[2]=唯一令牌
|
||||
redis.call("setex", KEYS[1], ARGV[1], ARGV[2])
|
||||
-- 尝试获取锁:SET NX EX(只有 key 不存在时才设置,原子操作)
|
||||
if redis.call("set", KEYS[1], ARGV[2], "NX", "EX", ARGV[1]) == "OK" then
|
||||
return 1 -- 成功获取
|
||||
end
|
||||
-- 已持有锁且未过期,续期(防止业务未完成锁就释放)
|
||||
if redis.call("get", KEYS[1]) == ARGV[2] then
|
||||
redis.call("expire", KEYS[1], ARGV[1])
|
||||
return 1
|
||||
end
|
||||
return 0
|
||||
return 0 -- 被其他客户端持有
|
||||
`)
|
||||
|
||||
ok, err := script.Run(ctx, c, []string{"lock:order:" + orderId},
|
||||
// KEYS[1] = lock key, ARGV[1] = TTL 秒数, ARGV[2] = 唯一令牌(如 UUID)
|
||||
ok, err := script.Run(ctx, rdb, []string{"lock:order:" + orderId},
|
||||
lockTTL, clientToken).Int()
|
||||
if ok == 1 {
|
||||
defer unlock(clientToken)
|
||||
defer func() {
|
||||
// 解锁:只有持有者才能释放(Lua 保证原子性)
|
||||
unlockScript.Run(ctx, rdb, []string{"lock:order:" + orderId}, clientToken)
|
||||
}()
|
||||
doBiz() // 临界区代码
|
||||
}
|
||||
```
|
||||
@@ -355,6 +363,9 @@ flowchart LR
|
||||
> | 任务队列、订单事件 | Stream |
|
||||
> | 海量消息、高吞吐 | Kafka/RabbitMQ |
|
||||
|
||||
> [!tip] Stream 深入阅读
|
||||
> 本节仅覆盖 Stream 基础用法。Consumer Group 内部机制、消息确认与重试(XCLAIM/XAUTOCLAIM)、Dead Letter Queue 模式、容量管理等进阶内容,详见 [[hhs/Redis/15-Stream]]。
|
||||
|
||||
## 五、Keyspace Notifications —— 键事件监听
|
||||
|
||||
### 原理与配置
|
||||
|
||||
Reference in New Issue
Block a user