happysir/distributed-lock
Composer 安装命令:
composer require happysir/distributed-lock
包简介
A distributed lock based on PHP and redis(swoft)
README 文档
README
[TOC]
锁
加锁是访问临界资源时对资源的保护机制,加锁的目的是对并发访问和并发请求进行保护,未获取到锁的请求将无权操作资源。
临界区域指的是一块对公共资源进行访问的代码,并非一种机制或是算法。一个程序、进程、线程可以拥有多个临界区域
安装
composer require happysir/distributed-lock
配置
use Happysir\Lock\RedisLock; use Swoft\Redis\Pool; use Swoft\Redis\RedisDb; return [ // redis db 'redis' => [ 'class' => RedisDb::class, 'host' => '127.0.0.1', 'port' => 6379, 'database' => 0, 'option' => [ 'prefix' => 'swoft:', 'serializer' => Redis::SERIALIZER_NONE ] ], // redis pool Pool::DEFAULT_POOL => [ 'class' => Pool::class, 'redisDb' => \bean('redis'), 'minActive' => 10, 'maxActive' => 20, 'maxWait' => 0, 'maxWaitTime' => 0, 'maxIdleTime' => 60, ], // redis lock RedisLock::class => [ // redis pool 'pool' => Pool::DEFAULT_POOL, ] ];
详细参数:
poolRedis 连接池
使用
注解方式
当前组件提供了注解的方式使用分布式锁,使用方式如下:
<?php declare(strict_types=1); namespace App\Http\Controller; use Happysir\Lock\Annotation\Mapping\DistributedLock; use Swoft\Context\Context; use Swoft\Http\Message\Request; use Swoft\Http\Message\Response; use Swoft\Http\Server\Annotation\Mapping\Controller; use Swoft\Http\Server\Annotation\Mapping\RequestMapping; use Swoft\Http\Server\Router\Router; use Swoft\View\Renderer; use Swoole\Coroutine; use Throwable; /** * Class HomeController * @Controller() */ class HomeController { /** * @RequestMapping("/") * @DistributedLock(key="request.getUriPath()~':'~request.query('id')",ttl=6,type=DistributedLock::RETRY_TO_GET) * @throws Throwable */ public function index(Request $request): Response { Coroutine::sleep(1); return context()->getResponse(); } /** * @RequestMapping("/hello") * @DistributedLock(key="hello~':'~request.query('id')",ttl=6,type=DistributedLock::NON_BLOCKING) * @throws Throwable */ public function hello(Request $request): Response { Coroutine::sleep(1); return context()->getResponse(); } }
@DistributedLock注解说明
key锁资源唯一标识key,同一时间片只能由一个线程持有type锁类型DistributedLock::NON_BLOCKING类型,在获取锁失败时会直接抛出DistributedLockException异常DistributedLock::RETRY_TO_GET类型,在获取锁失败时,会重新尝试获取锁(每0.5s重试一次,最多重试retries次),超过最大重试次数后会抛出DistributedLockException异常
ttl锁的有效时间(ttls后锁会自动过期)errcode尝试持有锁时抛出的异常对应的codeerrmsg尝试持有锁时抛出的异常对应的msgretries重试次数(需要注意的是,重试次数过多,可能会造成系统负载上升,因此硬性限制最大重试次数为10次)
key 这里支持 symfony/expression-language 表达式,可以实现很多复杂的功能,详细文档。key 表达式内置 CLASS(类名) 和 METHOD(方法名称) 两个变量,方便开发者使用。详细使用参考Swoft服务限流章节
代码方式(显式使用)
DistributedLock::NON_BLOCKING
use Happysir\Lock\RedisLock; $distributedLock = bean(RedisLock::class); if (!$distributedLock->tryLock('test', 1)) { return false; } // 业务逻辑... $distributedLock->unLock();
DistributedLock::RETRY_TO_GET
use Happysir\Lock\RedisLock; $distributedLock = bean(RedisLock::class); // 加锁1s,重试3次 if (!$distributedLock->lock('test', 1, 3)) { return false; } // 业务逻辑... $distributedLock->unLock();
看门狗机制
存在这样一种场景,业务代码较为复杂,执行时长会超过我们申请锁的时间,这时候就可能有第二个线程成功申请锁,未达到我们想要的保护目的。
针对这样的场景,我们在组件中支持了锁自动续约机制-看门狗任务。
当我们成功获取锁后,程序会为我们创建一个协程,此协程的作用是续约我们的锁的过期时间。在锁被释放或者当前请求结束后,此协程会自动退出。
happysir/distributed-lock 适用场景与选型建议
happysir/distributed-lock 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 124 次下载、GitHub Stars 达 6, 最近一次更新时间为 2019 年 08 月 04 日, 在 PHP 生态内属于活跃度较高的组件。
我们在过去多个企业项目中使用过 happysir/distributed-lock 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 happysir/distributed-lock 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
统计信息
- 总下载量: 124
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 6
- 点击次数: 0
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: Apache-2.0
- 更新时间: 2019-08-04