it编程 > 编程语言 > Php

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

47人参与 2025-02-13 Php

在分布式系统中,如何确保多台机器之间不会产生竞争条件,是一个常见且重要的问题。hyperf-wise-locksmith 库作为 hyperf 框架中的一员,提供了一个高效、简洁的互斥锁解决方案。

本文将带你了解这个库的安装、特性、基本与高级功能,并结合实际应用场景,展示其在项目中的应用。

hyperf-wise-locksmith 库简介

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

安装

要在你的 hyperf 项目中使用 hyperf-wise-locksmith,你需要通过 composer 进行安装:

composer require pudongping/hyperf-wise-locksmith -vvv

确保你的环境满足以下要求:

特性

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

基本功能

文件锁(flock)

文件锁是一种简单的锁机制,它依赖于文件系统。以下是一个使用文件锁的示例:

    private function flock(float $amount)
    {
        $path = base_path . '/runtime/alex.lock.cache';
        $filehandler = fopen($path, 'a+');
        // fwrite($filehandler, sprintf("%s - %s \r\n", 'locked', microtime()));

        $res = $this->locker->flock($filehandler, function () use ($amount) {
            return $this->deductbalance($amount);
        });
        return $res;
    }

分布式锁(redislock)

分布式锁适用于分布式系统,它依赖于 redis。以下是一个使用分布式锁的示例:

    private function redislock(float $amount)
    {
        $res = $this->locker->redislock('redislock', function () use ($amount) {
            return $this->deductbalance($amount);
        }, 10);
        return $res;
    }

高级功能

红锁(redlock)

红锁是一种更安全的分布式锁实现,它需要多个 redis 实例。以下是一个使用红锁的示例:

    private function redlock(float $amount)
    {
        $res = $this->locker->redlock('redlock', function () use ($amount) {
            return $this->deductbalance($amount);
        }, 10);
        return $res;
    }

协程级别的互斥锁(channellock)

协程级别的互斥锁适用于协程环境,它提供了一种轻量级的锁机制。以下是一个使用协程锁的示例:

    private function channellock(float $amount)
    {
        $res = $this->locker->channellock('channellock', function () use ($amount) {
            return $this->deductbalance($amount);
        });
        return $res;
    }

实际应用场景

假设我们有一个在线支付系统,需要在多个请求中扣减用户的余额。如果不使用互斥锁,可能会导致超扣或扣减失败。使用 hyperf-wise-locksmith 库,我们可以确保每次扣减操作都是原子性的。

代码示例

以下是一个扣减用户余额的示例,使用了 hyperf-wise-locksmith 库:

<?php
declare(strict_types=1);

namespace app\services;

use hyperf\contract\stdoutloggerinterface;
use pudongping\hyperfwiselocksmith\locker;
use pudongping\wiselocksmith\exception\wiselocksmithexception;
use pudongping\wiselocksmith\support\swoole\swooleengine;
use throwable;

class accountbalanceservice
{

    /**
     * 用户账户初始余额
     *
     * @var float|int
     */
    private float|int $balance = 10;

    public function __construct(
        private stdoutloggerinterface $logger,
        private locker                $locker
    ) {
        $this->locker->setlogger($logger);
    }

    private function deductbalance(float|int $amount)
    {
        if ($this->balance >= $amount) {
            // 模拟业务处理耗时
            usleep(500 * 1000);
            $this->balance -= $amount;
        }

        return $this->balance;
    }

    /**
     * @return float
     */
    private function getbalance(): float
    {
        return $this->balance;
    }

    public function runlock(int $i, string $type, float $amount)
    {
        try {
            $start = microtime(true);

            switch ($type) {
                case 'flock':
                    $this->flock($amount);
                    break;
                case 'redislock':
                    $this->redislock($amount);
                    break;
                case 'redlock':
                    $this->redlock($amount);
                    break;
                case 'channellock':
                    $this->channellock($amount);
                    break;
                case 'nomutex':
                default:
                    $this->deductbalance($amount);
                    break;
            }

            $balance = $this->getbalance();
            $id = swooleengine::id();
            $cost = microtime(true) - $start;
            $this->logger->notice('[{type} {cost}] ==> [{i}<=>{id}] ==> 当前用户的余额为:{balance}', compact('type', 'i', 'balance', 'id', 'cost'));

            return $balance;
        } catch (wiselocksmithexception|throwable $e) {
            return sprintf('err msg: %s ====> %s', $e, $e->getprevious());
        }
    }

}

然后我们再写一个控制器进行调用

<?php

declare(strict_types=1);

namespace app\controller;

use hyperf\httpserver\annotation\autocontroller;
use app\services\accountbalanceservice;
use hyperf\coroutine\parallel;
use function \hyperf\support\make;

#[autocontroller]
class balancecontroller extends abstractcontroller
{

    // curl '127.0.0.1:9511/balance/consumer?type=nomutex'
    public function consumer()
    {
        $type = $this->request->input('type', 'nomutex');
        $amount = (float)$this->request->input('amount', 1);

        $parallel = new parallel();
        $balance = make(accountbalanceservice::class);

        // 模拟 20 个并发
        for ($i = 1; $i <= 20; $i++) {
            $parallel->add(function () use ($balance, $i, $type, $amount) {
                return $balance->runlock($i, $type, $amount);
            }, $i);
        }

        $result = $parallel->wait();

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

}

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

注意

关于使用到 redislockredlock 时:

文档

详细文档可见 pudongping/wise-locksmith

结语

hyperf-wise-locksmith 库为 hyperf 框架的开发者提供了强大的互斥锁功能,可以帮助我们在高并发场景下保护共享资源。

通过本文的介绍,希望你能对 hyperf-wise-locksmith 有一个全面的了解,并在你的项目中灵活运用。如果你觉得这个库对你有帮助,希望你可以帮忙点个 star 哟~

以上就是详解php中互斥锁库hyperf-wise-locksmith的使用的详细内容,更多关于php hyperf-wise-locksmith的资料请关注代码网其它相关文章!

(0)
打赏 微信扫一扫 微信扫一扫

您想发表意见!!点此发布评论

推荐阅读

使用PHP和Xunsearch实现歌曲搜索功能

02-13

PHP使用OCR技术实现识别图片中的文字

02-13

基于PHP实现一个简单的http服务器

02-13

PHP使用互斥锁确保代码的线程安全的操作示例

02-13

PHP使用PHPExcel读取excel数据并批量上传到数据库

02-13

PHP执行php.exe -v命令报错的解决方案

02-13

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论