浦东平/wise-locksmith

用于独占代码执行的互斥锁库。

1.0.1 2023-08-24 03:46 UTC

This package is auto-updated.

Last update: 2024-09-24 05:59:23 UTC


README

Latest Stable Version Total Downloads Latest Unstable Version Minimum PHP Version Packagist License

英语 | 中文

🔒 一个无框架的互斥锁库,旨在在高并发场景下简化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());
}

致谢

贡献

可以通过问题跟踪器提交错误报告(以及小型补丁)。对于重大补丁,推荐Fork仓库并提交Pull Request。

许可证

MIT,见LICENSE文件