Lavavel5.5源代码 - 并发数控制
2024-08-27 04:28:20
app('redis')->connection('default')->funnel('key000')
// 每个资源最大锁定10秒自动过期,只有60个资源(并发),在3秒内获取不到锁抛出异常
->releaseAfter(10)->limit(60)->block(3)
->then(function () {
// 获取锁成功,执行业务
}, function () {
// 获取锁失败
return false;
});
<?php namespace Illuminate\Redis\Limiters; use Illuminate\Contracts\Redis\LimiterTimeoutException; class ConcurrencyLimiter
{
/**
* The Redis factory implementation.
*
* @var \Illuminate\Redis\Connections\Connection
*/
protected $redis; /**
* The name of the limiter.
*
* @var string
*/
protected $name; /**
* The allowed number of concurrent tasks.
*
* @var int
*/
protected $maxLocks; /**
* The number of seconds a slot should be maintained.
*
* @var int
*/
protected $releaseAfter; /**
* Create a new concurrency limiter instance.
*
* @param \Illuminate\Redis\Connections\Connection $redis
* @param string $name
* @param int $maxLocks
* @param int $releaseAfter
* @return void
*/
public function __construct($redis, $name, $maxLocks, $releaseAfter)
{
$this->name = $name;
$this->redis = $redis;
$this->maxLocks = $maxLocks;
$this->releaseAfter = $releaseAfter;
} /**
* Attempt to acquire the lock for the given number of seconds.
*
* @param int $timeout
* @param callable|null $callback
* @return bool
* @throws \Illuminate\Contracts\Redis\LimiterTimeoutException
*/
public function block($timeout, $callback = null)
{
$starting = time(); while (! $slot = $this->acquire()) {
if (time() - $timeout >= $starting) {
throw new LimiterTimeoutException;
} usleep(250 * 1000);
} if (is_callable($callback)) {
return tap($callback(), function () use ($slot) {
$this->release($slot);
});
} return true;
} /**
* Attempt to acquire the lock.
*
* @return mixed
*/
protected function acquire()
{
$slots = array_map(function ($i) {
return $this->name.$i;
}, range(1, $this->maxLocks)); return $this->redis->eval($this->luaScript(), count($slots),
...array_merge($slots, [$this->name, $this->releaseAfter])
);
} /**
* Get the Lua script for acquiring a lock.
*
* KEYS - The keys that represent available slots
* ARGV[1] - The limiter name
* ARGV[2] - The number of seconds the slot should be reserved
*
* @return string
*/
protected function luaScript()
{
return <<<'LUA'
for index, value in pairs(redis.call('mget', unpack(KEYS))) do
if not value then
redis.call('set', ARGV[1]..index, "1", "EX", ARGV[2])
return ARGV[1]..index
end
end
LUA;
} /**
* Release the lock.
*
* @param string $key
* @return void
*/
protected function release($key)
{
$this->redis->del($key);
}
}
最新文章
- Java开发的几个注意点
- 在Mac OS X Yosemite 10.10.3 中搭建第一个 ASP.NET 5 Web 项目
- CXF:通过WebService上传文件,包括大文件的处理
- Cocos2d-JS项目之一:环境(IDE 运行js-tests、IDE 和 studio 统一工程)
- main函数中argc和argv含义
- 关于WPF中Popup控件的小记
- CVPR读书笔记[5]:Gabor特征提取之Gabor核的实现
- USACO Section 2.1 Sorting a Three-Valued Sequence
- HTML之学习笔记(一)简介
- ElasticSearch(6)-结构化查询
- CSS行高line-height的一些深入理解及应用
- 【转】10款GitHub上最火爆的国产开源项目
- ZeroMQ 教程 002 : 高级技巧
- java 安装教程
- .Net高级进阶,教你如何构建企业模型数据拦截层,动态控制字段验证
- 大规模数据导入和导出(oracle)
- Flask-WTF表单的使用
- Iterator和Iterable的区别以及使用
- python --- 10 *args **kwargs 命名空间 作用域 函数的嵌套
- Materialize和Material Design Lite的区别
热门文章
- javascript typeof()的用法与运算符用法
- django模板templates详解(二)
- Linux(Ubuntu) 常用命令
- 让ADO.NET Entity Framework 支持ACCESS数据库
- OC 内存管理(retain和release)
- 如何解决“请考虑使用 app.config 将程序集“XXXXXXXX”从版本XXXX重新映射到版本XXXX”的问题
- 访问google的若干解决办法
- maven学习记录二——依赖管理
- java连接数据库(sqlserver和mysql)
- Ueditor插入script标签