详解PHP中互斥锁库hyperf-wise-locksmith的使用
在分布式系统中如何确保多台机器之间不会产生竞争条件是一个常见且重要的问题。hyperf-wise-locksmith库作为Hyperf框架中的一员提供了一个高效、简洁的互斥锁解决方案。本文将带你了解这个库的安装、特性、基本与高级功能并结合实际应用场景展示其在项目中的应用。hyperf-wise-locksmith 库简介hyperf-wise-locksmith是一个适配 Hyperf 框架的互斥锁库它基于pudongping/wise-locksmith库构建。它可以帮助我们在分布式环境下进行锁的管理确保同一时刻只有一个进程能够操作某些共享资源从而避免数据的竞争和不一致问题。安装要在你的 Hyperf 项目中使用hyperf-wise-locksmith你需要通过 Composer 进行安装1composer require pudongping/hyperf-wise-locksmith-vvv确保你的环境满足以下要求PHP 8.0hyperf ~3.0.0。特性hyperf-wise-locksmith提供了多种锁机制包括文件锁、分布式锁、红锁和协程级别的互斥锁。这些锁机制可以帮助开发者在不同的场景下保护共享资源避免竞态条件。基本功能文件锁flock文件锁是一种简单的锁机制它依赖于文件系统。以下是一个使用文件锁的示例1234567891011privatefunctionflock(float$amount){$path BASE_PATH ./runtime/alex.lock.cache;$fileHandlerfopen($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。以下是一个使用分布式锁的示例1234567privatefunctionredisLock(float$amount){$res$this-locker-redisLock(redisLock,function()use($amount) {return$this-deductBalance($amount);}, 10);return$res;}高级功能红锁redLock红锁是一种更安全的分布式锁实现它需要多个 Redis 实例。以下是一个使用红锁的示例1234567privatefunctionredLock(float$amount){$res$this-locker-redLock(redLock,function()use($amount) {return$this-deductBalance($amount);}, 10);return$res;}协程级别的互斥锁channelLock协程级别的互斥锁适用于协程环境它提供了一种轻量级的锁机制。以下是一个使用协程锁的示例1234567privatefunctionchannelLock(float$amount){$res$this-locker-channelLock(channelLock,function()use($amount) {return$this-deductBalance($amount);});return$res;}实际应用场景假设我们有一个在线支付系统需要在多个请求中扣减用户的余额。如果不使用互斥锁可能会导致超扣或扣减失败。使用hyperf-wise-locksmith库我们可以确保每次扣减操作都是原子性的。代码示例以下是一个扣减用户余额的示例使用了hyperf-wise-locksmith库1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283?phpdeclare(strict_types1);namespaceApp\Services;useHyperf\Contract\StdoutLoggerInterface;usePudongping\HyperfWiseLocksmith\Locker;usePudongping\WiseLocksmith\Exception\WiseLocksmithException;usePudongping\WiseLocksmith\Support\Swoole\SwooleEngine;useThrowable;classAccountBalanceService{/*** 用户账户初始余额** var float|int*/privatefloat|int$balance 10;publicfunction__construct(privateStdoutLoggerInterface$logger,privateLocker$locker) {$this-locker-setLogger($logger);}privatefunctiondeductBalance(float|int$amount){if($this-balance $amount) {// 模拟业务处理耗时usleep(500 * 1000);$this-balance -$amount;}return$this-balance;}/*** return float*/privatefunctiongetBalance(): float{return$this-balance;}publicfunctionrunLock(int$i, string$type, float$amount){try{$start microtime(true);switch($type) {caseflock:$this-flock($amount);break;caseredisLock:$this-redisLock($amount);break;caseredLock:$this-redLock($amount);break;casechannelLock:$this-channelLock($amount);break;casenoMutex: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) {returnsprintf(Err Msg: %s %s,$e,$e-getPrevious());}}}然后我们再写一个控制器进行调用12345678910111213141516171819202122232425262728293031323334353637?phpdeclare(strict_types1);namespaceApp\Controller;useHyperf\HttpServer\Annotation\AutoController;useApp\Services\AccountBalanceService;useHyperf\Coroutine\Parallel;usefunction\Hyperf\Support\make;#[AutoController]classBalanceControllerextendsAbstractController{// curl 127.0.0.1:9511/balance/consumer?typenoMutexpublicfunctionconsumer(){$type$this-request-input(type,noMutex);$amount (float)$this-request-input(amount, 1);$parallelnewParallel();$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?typenoMutex地址时我们可以看到用户的余额会被扣成负数这明显不符合逻辑。 然而当我们访问下面几个地址时我们可以看到用户余额不会被扣成负数则说明很好的保护了竞态下的共享资源的准确性。/balance/consumer?typeflock文件锁/balance/consumer?typeredisLock分布式锁/balance/consumer?typeredLock红锁/balance/consumer?typechannelLock协程级别的互斥锁注意关于使用到redisLock和redLock时使用redisLock默认采用的config/autoload/redis.php配置文件中的第一个key配置 redis 实例即default。可按需传入第 4 个参数string|null $redisPoolName进行重新指定。使用redLock默认采用的config/autoload/redis.php配置文件中的所有key对应的配置 redis 实例。可按需传入第 4 个参数?array $redisPoolNames null进行重新指定。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2486219.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!