浦东平 / wise-locksmith
用于独占代码执行的互斥锁库。
Requires (Dev)
- phpunit/phpunit: *
- swoole/ide-helper: ^4.5 | ^5.0
This package is auto-updated.
Last update: 2024-09-24 05:59:23 UTC
README
英语 | 中文
🔒 一个无框架的互斥锁库,旨在在高并发场景下简化PHP代码的序列化执行。
要求
- PHP >= 7.1 或更高版本
- Redis >= 2.6.12 或更高版本(用于分布式锁或Redlock)
- Swoole >= 4.5 或更高版本(用于协程级别的互斥锁)
安装
composer require pudongping/wise-locksmith
快速入门
<?php require 'vendor/autoload.php'; use Pudongping\WiseLocksmith\Locker; $redisHosts = [ [ 'host' => '127.0.0.1', 'port' => 6379 ], [ 'host' => '127.0.0.1', 'port' => 6380 ], [ 'host' => '127.0.0.1', 'port' => 6381 ], [ 'host' => '127.0.0.1', 'port' => 6382 ], [ 'host' => '127.0.0.1', 'port' => 6383 ], ]; // Initialize Redis instances if distributed locks or Redlock are needed; otherwise, you can skip this step $redisInstances = array_map(function ($v) { $redis = new \Redis(); $redis->connect($v['host'], $v['port']); return $redis; }, $redisHosts); // Create an instance of locker $locker = new Locker();
用法
当前项目中提供了一个在高并发场景下潜在数据不一致性的示例,请查看这里。
flock - 文件锁
文件锁没有依赖。您可以使用可选的第三个参数设置锁的超时时间,以秒为单位(支持浮点数,例如,1.5表示1500毫秒,这意味着它将等待最多1500毫秒;如果无法获取锁,它将主动释放尝试并抛出 Pudongping\WiseLocksmith\Exception\TimeoutException
异常)。将其设置为 Pudongping\WiseLocksmith\Lock\File\Flock::INFINITE_TIMEOUT
表示它永远不会过期,并且它将不断尝试获取锁直到成功。默认值是 Pudongping\WiseLocksmith\Lock\File\Flock::INFINITE_TIMEOUT
。
$path = tempnam(sys_get_temp_dir(), 'wise-locksmith-flock-'); $fileHandler = fopen($path, 'r'); $res = $locker->flock($fileHandler, function () { // Write the code you want to protect here }); unlink($path); return $res;
redisLock - 分布式锁
需要 redis
扩展。您可以使用可选的第三个参数设置锁的超时时间,以秒为单位(支持浮点数,例如,1.5表示1500毫秒,这意味着它将等待最多1500毫秒;如果无法获取锁,它将主动释放尝试并抛出 Pudongping\WiseLocksmith\Exception\TimeoutException
异常)。默认值是 5
。第四个参数是当前锁的唯一值,通常不需要设置,除非有特殊情况。
$res = $locker->redisLock($redisInstances[0], 'redisLock', function () { // Write the code you want to protect here }); return $res;
redLock - RedLock(Redis集群环境中分布式锁的实现)
设置 redLock
锁所需的参数与 redisLock
锁相同,除了第一个参数。所有其他参数完全相同。redLock
锁是 redisLock
锁的集群实现。
$res = $locker->redLock($redisInstances, 'redLock', function () { // Write the code you want to protect here }); return $res;
channelLock - 协程级别互斥锁
使用此锁时,您需要安装 swoole
扩展,版本必须大于或等于 4.5
。您可以使用可选的第三个参数设置锁的超时时间,以秒为单位(支持浮点数,例如,1.5表示1500毫秒,这意味着它将等待最多1500毫秒;如果无法获取锁,它将主动放弃尝试并返回 false
以指示未获取到锁)。将其设置为 -1
表示它永远不会过期,并且它将不断尝试获取锁直到成功。默认值是 -1
。
$res = $locker->channelLock('channelLock', function () { // Write the code you want to protect here }); return $res;
对于所有提到的锁,只有在成功获取锁之后才会执行业务关闭函数。然后返回业务关闭函数执行的结果。否则,如果未获取到锁,则不执行业务关闭函数,并返回 null
。
运行测试
要运行测试套件,请克隆此存储库,然后使用Composer安装依赖项。
composer install
然后,转到项目根目录并运行
php -d memory_limit=-1 ./vendor/bin/phpunit -c ./phpunit.xml.dist
or
composer run test
异常处理
您可以通过捕获 Pudongping\WiseLocksmith\Exception\WiseLocksmithException
异常来捕获此库抛出的所有异常。
use Pudongping\WiseLocksmith\Exception\WiseLocksmithException; use Pudongping\WiseLocksmith\Locker; try { $locker = new Locker(); // ... } catch (WiseLocksmithException $exception) { var_dump($exception->getPrevious()); var_dump($exception->getCode(), $exception->getMessage()); }
致谢
- laravel/framework
- hyperf/context
- easy-swoole/组件
- swoole/库
- redisson/redisson
- php-lock/锁
- 如何实现分布式锁?
- Redlock 安全吗?
- 使用 Redis 的分布式锁 , 一种基于 Redis 的分布式锁模式(中文译文)
贡献
可以通过问题跟踪器提交错误报告(以及小型补丁)。对于重大补丁,推荐Fork仓库并提交Pull Request。
许可证
MIT,见LICENSE文件。