下面我用**「是什么 → 能做什么 → 怎么用 → 典型场景 → 注意事项」**的结构,系统、实战化地给你详解
👉 PHP 互斥锁库:hyperf-wise-locksmith
一、hyperf-wise-locksmith 是什么?
hyperf-wise-locksmith 是 Hyperf 生态中一个统一的分布式互斥锁(Mutex Lock)抽象库,核心目标是:
用同一套 API,安全地操作不同后端的锁(Redis / MySQL / 文件 / 内存)
它本质上解决的是 高并发下的资源竞争问题:
- 防止重复执行
- 防止超卖 / 重复扣减
- 防止并发写冲突
- 防止定时任务重叠执行
二、它能解决什么问题?
典型痛点(你一定遇到过)
| 场景 | 问题 |
|---|---|
| 秒杀 / 抢购 | 多个请求同时扣库存 |
| 定时任务 | cron 多实例同时跑 |
| 消息消费 | 同一消息被多次处理 |
| 接口幂等 | 重复提交订单 |
| 分布式环境 | 单机锁(flock)失效 |
wise-locksmith = 分布式安全锁
三、支持的锁驱动(非常关键)
hyperf-wise-locksmith 并不直接实现锁
👉 它是一个「锁调度器」
常见驱动包括:
| 驱动 | 说明 |
|---|---|
| Redis | 最常用(推荐) |
| MySQL | 适合无 Redis 环境 |
| 文件锁 | 单机调试 |
| 内存锁 | 单进程测试 |
四、安装方式
composer require hyperf/wise-locksmith
前提:你在 Hyperf 框架中使用
五、核心概念(一定要理解)
1️⃣ Lock(锁对象)
- 表示一个互斥资源
- 通过 唯一 key 标识
$orderLock = $lockFactory->create('order:123');
2️⃣ LockFactory(锁工厂)
统一创建锁实例:
use Hyperf\WiseLocksmith\LockFactory;
public function __construct(
private LockFactory $lockFactory
) {}
3️⃣ 锁的生命周期
获取锁 → 执行业务 → 释放锁
六、最基础用法(强烈建议这样写)
示例:防止订单重复处理
$lock = $this->lockFactory->create('order:'.$orderId);
if ($lock->acquire()) {
try {
// 业务逻辑
$this->processOrder($orderId);
} finally {
$lock->release();
}
}
✅ 为什么一定要 try...finally?
- 防止异常导致死锁
- finally 永远会执行
七、带超时的锁(生产必用)
1️⃣ 获取锁超时时间
$lock = $this->lockFactory->create(
'order:'.$orderId,
5 // 锁过期时间(秒)
);
避免服务宕机后锁永远不释放
2️⃣ 阻塞等待锁(可选)
$lock->acquire(3); // 最多等待 3 秒
| 结果 | 含义 |
|---|---|
| true | 成功拿到锁 |
| false | 等待超时 |
八、最推荐的写法:withLock(语义最清晰)
$this->lockFactory->create('pay:'.$orderId, 5)
->withLock(function () use ($orderId) {
$this->pay($orderId);
});
优点
- 自动 acquire + release
- 不容易写错
- 代码更干净
九、Redis 分布式锁原理(你要懂)
内部做了什么?
- 使用
SET key value NX EX ttl - value 是唯一标识(防止误删)
- 释放时校验 value
👉 这是安全版的 Redis 锁,不是 naive 实现
十、典型实战场景
✅ 场景 1:库存扣减(防超卖)
$this->lockFactory->create('stock:'.$skuId, 3)
->withLock(function () use ($skuId) {
$stock = $this->stockDao->get($skuId);
if ($stock <= 0) {
throw new BusinessException('库存不足');
}
$this->stockDao->decrement($skuId);
});
✅ 场景 2:定时任务防重入
$this->lockFactory->create('cron:sync_user', 60)
->withLock(function () {
$this->syncUser();
});
✅ 场景 3:接口幂等
$key = 'idempotent:' . $requestId;
if (! $this->lockFactory->create($key, 10)->acquire()) {
throw new RepeatRequestException();
}
十一、常见坑(一定要看)
❌ 锁 key 不唯一
// 错误
create('order');
// 正确
create('order:' . $orderId);
❌ 锁时间太短
- 业务未完成
- 锁提前失效
- 并发穿透
👉 TTL ≥ 业务最长执行时间
❌ 不释放锁
- 没有 try-finally
- 异常直接 return
十二、和你可能用过的锁对比
| 方案 | 问题 |
|---|---|
| flock | 只能单机 |
| Redis 手写锁 | 容易写错 |
| MySQL for update | 性能差 |
| wise-locksmith | 统一、安全、规范 |
十三、适合你吗?
✅ 非常适合你如果:
- Hyperf 项目
- 高并发接口
- 多实例部署
- 分布式任务 / MQ
❌ 不适合:
- 单脚本 PHP
- 无并发需求
十四、一句话总结
hyperf-wise-locksmith 不是“锁”,而是一套「安全使用分布式锁的最佳实践封装」