modify: 排他锁
This commit is contained in:
@@ -52,8 +52,41 @@ cache.close() # 释放连接
|
||||
with Cache.from_config(cfg) as cache: ... # 上下文管理器,退出自动 close
|
||||
|
||||
cache.client # 底层客户端逃生口(diskcache.Cache / redis.Redis)
|
||||
|
||||
# 原子写(分布式锁原语):仅当 key 不存在时写入,成功返回 True,已存在返回 False,不覆盖
|
||||
ok = cache.backend.set_nx("leader", {"node": "gw-1"}, expire=30)
|
||||
```
|
||||
|
||||
### 分布式排他锁 `DistributedLock`
|
||||
|
||||
基于 `backend.set_nx`(SET NX + TTL 租约)实现的**跨进程/跨主机排他锁**,用于集群协调(如保证全局只有一个 MQTT Bridge 消费):
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from chongming_cache import Cache, DistributedLock
|
||||
|
||||
async def main():
|
||||
cache = Cache.from_config(config["cache"])
|
||||
lock = DistributedLock(cache, "mqtt_bridge", ttl=30, renew_interval=10)
|
||||
if not lock.acquire(): # 全局唯一持锁方返回 True,其余返回 False
|
||||
print("其他实例已持有,跳过")
|
||||
return
|
||||
lock.start() # 后台自动续约(防宕机/长暂停导致锁过期被抢)
|
||||
try:
|
||||
... # 执行受保护的单例任务
|
||||
finally:
|
||||
await lock.stop() # 停止续约
|
||||
lock.release() # 受保护释放
|
||||
cache.close()
|
||||
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
- `acquire()`:SET NX,原子地仅在不存在时写入;key 带 TTL 租约,持有方宕机后到期自动让出,不会死锁。
|
||||
- `start()` / `stop()`:后台续约任务;续约前校验 token,仅在自己仍持有时 `touch`,锁丢失即停止续约。
|
||||
- `release()`:受保护释放——仅当 token 仍匹配(仍是自己持有)才删除,绝不误删其他进程/主机抢到的锁。
|
||||
- **后端适用性**:`redis` 真正跨主机共享;`diskcache` 进程安全(SQLite),可用于单机多进程或共享卷场景,不可跨无共享文件系统的主机。
|
||||
|
||||
---
|
||||
|
||||
## 后端配置(config.toml `[cache]` 段)
|
||||
|
||||
Reference in New Issue
Block a user