直接 composer require php-lock/php-lock 失败是因为该包未注册到 Packagist,GitHub 仓库既无稳定 tag 也未提交至 packagist.org,需通过 "repositories" 配置 "type": "vcs" 手动引入并指定 dev-main 版本。

为什么直接 composer require php-lock/php-lock 会失败
因为 php-lock/php-lock 并不是 Packagist 上的正式包,它没有注册到 Composer 默认源。你执行命令后大概率看到:Could not find package php-lock/php-lock。这不是你网络或配置问题,是项目本身未发布——它的 GitHub 仓库(php-lock/php-lock)只提供源码,没打 tag,也没提交到 packagist.org。
正确做法是用 repositories 手动引入:
{
"repositories": [
{
"type": "vcs",
"url": "https://github.com/php-lock/php-lock"
}
],
"require": {
"php-lock/php-lock": "dev-main"
}
}
注意两点:
-
"type": "vcs"是必须的,package类型不适用(它需要完整描述,太重) - 版本只能写
dev-main或具体 commit hash(如dev-main#abc123),不能写^1.0——仓库无稳定 tag
如何初始化 FileLock 和 RedisLock 实例
库提供两个核心实现:FileLock 和 RedisLock,但它们的构造参数差异大,容易传错。
立即学习“PHP免费学习笔记(深入)”;
FileLock 需要一个可写的目录路径,不是文件路径:
use PhpLock\Lock\FileLock;
$lock = new FileLock('/tmp/myapp-locks/'); // ✅ 末尾带斜杠,且目录需存在、可写
// ❌ new FileLock('/tmp/myapp-locks/lock.txt') 会报错:not a directory
RedisLock 接收的是 Predis\Client 或 Redis 实例,**不接受 DSN 字符串**:
use PhpLock\Lock\RedisLock; use Predis\Client; $client = new Client(['tcp://127.0.0.1:6379']); $lock = new RedisLock($client, 'myapp:lock:'); // 第二个参数是 key 前缀,非必需但建议设
如果你用 PHP 内置 Redis 扩展,也得先实例化:
$redis = new \Redis();
$redis->connect('127.0.0.1', 6379);
$lock = new RedisLock($redis, 'myapp:lock:');
acquire() 返回 false 却不报错?检查超时和重试逻辑
acquire() 默认不阻塞,立即返回 bool,很多同学以为“没报异常就是成功”,结果并发下锁失效。
关键参数是 $timeout(单位秒)和 $retryInterval(单位微秒):
-
$timeout = 0→ 纯非阻塞,抢不到立刻返回false -
$timeout = 10→ 最多等 10 秒,期间按$retryInterval间隔重试 -
$retryInterval默认是100000(即 100ms),太频繁可能压 Redis;太长(如 2s)会导致实际等待远超 timeout
典型安全用法:
if (!$lock->acquire('order-pay-12345', 30, 500000)) { // 等 30 秒,每 500ms 试一次
throw new RuntimeException('Failed to acquire lock for order-pay-12345');
}
// ... 执行临界区逻辑
$lock->release('order-pay-12345');
注意:release() 必须显式调用,它不会自动在脚本结束时释放(FileLock 没有自动清理机制,RedisLock 依赖 key 过期,但主动 release 更可靠)。
FileLock 在容器或共享存储下容易失效
FileLock 本质是基于 flock() + 临时文件,它在以下场景不可靠:
- Docker 多副本共用同一宿主机目录,但不同容器进程无法看到彼此的 flock
- NFS 或某些云存储(如阿里云 NAS)不完全支持 POSIX 文件锁
- PHP 运行用户(如 www-data)对锁目录无写权限,
flock()静默失败
验证方式很简单:
var_dump(is_writable('/tmp/myapp-locks/')); // 必须 true
var_dump(function_exists('flock')); // 必须 true
生产环境强烈建议优先用 RedisLock,哪怕只起一个单节点 Redis——它跨进程、跨机器、自带过期,语义更清晰。FileLock 仅适合单机 CLI 脚本或开发调试。



















