• 设为首页
  • 收藏本站
  • 积分充值
  • VIP赞助
  • 手机版
  • 微博
  • 微信
    微信公众号 添加方式:
    1:搜索微信号(888888
    2:扫描左侧二维码
  • 快捷导航
    福建二哥 门户 查看主题

    详解PHP中互斥锁库hyperf-wise-locksmith的使用

    发布者: 网神之王 | 发布时间: 2025-6-14 13:15| 查看数: 136| 评论数: 0|帖子模式

    在分布式系统中,如何确保多台机器之间不会产生竞争条件,是一个常见且重要的问题。
    1. hyperf-wise-locksmith
    复制代码
    库作为
    1. Hyperf
    复制代码
    框架中的一员,提供了一个高效、简洁的互斥锁解决方案。
    本文将带你了解这个库的安装、特性、基本与高级功能,并结合实际应用场景,展示其在项目中的应用。

    hyperf-wise-locksmith 库简介
    1. hyperf-wise-locksmith
    复制代码
    是一个适配 Hyperf 框架的互斥锁库,它基于
    1. pudongping/wise-locksmith
    复制代码
    库构建。它可以帮助我们在分布式环境下进行锁的管理,确保同一时刻只有一个进程能够操作某些共享资源,从而避免数据的竞争和不一致问题。

    安装

    要在你的 Hyperf 项目中使用
    1. hyperf-wise-locksmith
    复制代码
    ,你需要通过 Composer 进行安装:
    1. composer require pudongping/hyperf-wise-locksmith -vvv
    复制代码
    确保你的环境满足以下要求:

    • PHP >= 8.0
    • hyperf ~3.0.0。

    特性
    1. hyperf-wise-locksmith
    复制代码
    提供了多种锁机制,包括文件锁分布式锁红锁协程级别的互斥锁。这些锁机制可以帮助开发者在不同的场景下保护共享资源,避免竞态条件。

    基本功能


    文件锁(flock)

    文件锁是一种简单的锁机制,它依赖于文件系统。以下是一个使用文件锁的示例:
    1.     private function flock(float $amount)
    2.     {
    3.         $path = BASE_PATH . '/runtime/alex.lock.cache';
    4.         $fileHandler = fopen($path, 'a+');
    5.         // fwrite($fileHandler, sprintf("%s - %s \r\n", 'Locked', microtime()));

    6.         $res = $this->locker->flock($fileHandler, function () use ($amount) {
    7.             return $this->deductBalance($amount);
    8.         });
    9.         return $res;
    10.     }
    复制代码
    分布式锁(redisLock)

    分布式锁适用于分布式系统,它依赖于 Redis。以下是一个使用分布式锁的示例:
    1.     private function redisLock(float $amount)
    2.     {
    3.         $res = $this->locker->redisLock('redisLock', function () use ($amount) {
    4.             return $this->deductBalance($amount);
    5.         }, 10);
    6.         return $res;
    7.     }
    复制代码
    高级功能


    红锁(redLock)

    红锁是一种更安全的分布式锁实现,它需要多个 Redis 实例。以下是一个使用红锁的示例:
    1.     private function redLock(float $amount)
    2.     {
    3.         $res = $this->locker->redLock('redLock', function () use ($amount) {
    4.             return $this->deductBalance($amount);
    5.         }, 10);
    6.         return $res;
    7.     }
    复制代码
    协程级别的互斥锁(channelLock)

    协程级别的互斥锁适用于协程环境,它提供了一种轻量级的锁机制。以下是一个使用协程锁的示例:
    1.     private function channelLock(float $amount)
    2.     {
    3.         $res = $this->locker->channelLock('channelLock', function () use ($amount) {
    4.             return $this->deductBalance($amount);
    5.         });
    6.         return $res;
    7.     }
    复制代码
    实际应用场景

    假设我们有一个在线支付系统,需要在多个请求中扣减用户的余额。如果不使用互斥锁,可能会导致超扣或扣减失败。使用
    1. hyperf-wise-locksmith
    复制代码
    库,我们可以确保每次扣减操作都是原子性的。
    代码示例
    以下是一个扣减用户余额的示例,使用了
    1. hyperf-wise-locksmith
    复制代码
    库:
    1. <?php
    2. declare(strict_types=1);

    3. namespace App\Services;

    4. use Hyperf\Contract\StdoutLoggerInterface;
    5. use Pudongping\HyperfWiseLocksmith\Locker;
    6. use Pudongping\WiseLocksmith\Exception\WiseLocksmithException;
    7. use Pudongping\WiseLocksmith\Support\Swoole\SwooleEngine;
    8. use Throwable;

    9. class AccountBalanceService
    10. {

    11.     /**
    12.      * 用户账户初始余额
    13.      *
    14.      * @var float|int
    15.      */
    16.     private float|int $balance = 10;

    17.     public function __construct(
    18.         private StdoutLoggerInterface $logger,
    19.         private Locker                $locker
    20.     ) {
    21.         $this->locker->setLogger($logger);
    22.     }

    23.     private function deductBalance(float|int $amount)
    24.     {
    25.         if ($this->balance >= $amount) {
    26.             // 模拟业务处理耗时
    27.             usleep(500 * 1000);
    28.             $this->balance -= $amount;
    29.         }

    30.         return $this->balance;
    31.     }

    32.     /**
    33.      * @return float
    34.      */
    35.     private function getBalance(): float
    36.     {
    37.         return $this->balance;
    38.     }

    39.     public function runLock(int $i, string $type, float $amount)
    40.     {
    41.         try {
    42.             $start = microtime(true);

    43.             switch ($type) {
    44.                 case 'flock':
    45.                     $this->flock($amount);
    46.                     break;
    47.                 case 'redisLock':
    48.                     $this->redisLock($amount);
    49.                     break;
    50.                 case 'redLock':
    51.                     $this->redLock($amount);
    52.                     break;
    53.                 case 'channelLock':
    54.                     $this->channelLock($amount);
    55.                     break;
    56.                 case 'noMutex':
    57.                 default:
    58.                     $this->deductBalance($amount);
    59.                     break;
    60.             }

    61.             $balance = $this->getBalance();
    62.             $id = SwooleEngine::id();
    63.             $cost = microtime(true) - $start;
    64.             $this->logger->notice('[{type} {cost}] ==> [{i}<=>{id}] ==> 当前用户的余额为:{balance}', compact('type', 'i', 'balance', 'id', 'cost'));

    65.             return $balance;
    66.         } catch (WiseLocksmithException|Throwable $e) {
    67.             return sprintf('Err Msg: %s ====> %s', $e, $e->getPrevious());
    68.         }
    69.     }

    70. }
    复制代码
    然后我们再写一个控制器进行调用
    1. <?php

    2. declare(strict_types=1);

    3. namespace App\Controller;

    4. use Hyperf\HttpServer\Annotation\AutoController;
    5. use App\Services\AccountBalanceService;
    6. use Hyperf\Coroutine\Parallel;
    7. use function \Hyperf\Support\make;

    8. #[AutoController]
    9. class BalanceController extends AbstractController
    10. {

    11.     // curl '127.0.0.1:9511/balance/consumer?type=noMutex'
    12.     public function consumer()
    13.     {
    14.         $type = $this->request->input('type', 'noMutex');
    15.         $amount = (float)$this->request->input('amount', 1);

    16.         $parallel = new Parallel();
    17.         $balance = make(AccountBalanceService::class);

    18.         // 模拟 20 个并发
    19.         for ($i = 1; $i <= 20; $i++) {
    20.             $parallel->add(function () use ($balance, $i, $type, $amount) {
    21.                 return $balance->runLock($i, $type, $amount);
    22.             }, $i);
    23.         }

    24.         $result = $parallel->wait();

    25.         return $this->response->json($result);
    26.     }

    27. }
    复制代码
    当我们访问
    1. /balance/consumer?type=noMutex
    复制代码
    地址时,我们可以看到用户的余额会被扣成负数,这明显不符合逻辑。 然而当我们访问下面几个地址时,我们可以看到用户余额不会被扣成负数,则说明很好的保护了竞态下的共享资源的准确性。

      1. /balance/consumer?type=flock
      复制代码
      :文件锁
      1. /balance/consumer?type=redisLock
      复制代码
      :分布式锁
      1. /balance/consumer?type=redLock
      复制代码
      :红锁
      1. /balance/consumer?type=channelLock
      复制代码
      :协程级别的互斥锁

    注意

    关于使用到
    1. redisLock
    复制代码
    1. redLock
    复制代码
    时:

    • 使用
      1. redisLock
      复制代码
      默认采用的
      1. config/autoload/redis.php
      复制代码
      配置文件中的第一个
      1. key
      复制代码
      配置 redis 实例(即 default)。可按需传入第 4 个参数
      1. string|null $redisPoolName
      复制代码
      进行重新指定。
    • 使用
      1. redLock
      复制代码
      默认采用的
      1. config/autoload/redis.php
      复制代码
      配置文件中的所有
      1. key
      复制代码
      对应的配置 redis 实例。可按需传入第 4 个参数
      1. ?array $redisPoolNames = null
      复制代码
      进行重新指定。

    文档

    详细文档可见 pudongping/wise-locksmith

    结语
    1. hyperf-wise-locksmith
    复制代码
    库为 Hyperf 框架的开发者提供了强大的互斥锁功能,可以帮助我们在高并发场景下保护共享资源。
    通过本文的介绍,希望你能对
    1. hyperf-wise-locksmith
    复制代码
    有一个全面的了解,并在你的项目中灵活运用。如果你觉得这个库对你有帮助,希望你可以帮忙点个 Star 哟~
    以上就是详解PHP中互斥锁库hyperf-wise-locksmith的使用的详细内容,更多关于PHP hyperf-wise-locksmith的资料请关注脚本之家其它相关文章!

    来源:https://www.jb51.net/program/331550odl.htm
    免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

    最新评论

    QQ Archiver 手机版 小黑屋 福建二哥 ( 闽ICP备2022004717号|闽公网安备35052402000345号 )

    Powered by Discuz! X3.5 © 2001-2023

    快速回复 返回顶部 返回列表