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);
}
}

  

最新文章

  1. Java开发的几个注意点
  2. 在Mac OS X Yosemite 10.10.3 中搭建第一个 ASP.NET 5 Web 项目
  3. CXF:通过WebService上传文件,包括大文件的处理
  4. Cocos2d-JS项目之一:环境(IDE 运行js-tests、IDE 和 studio 统一工程)
  5. main函数中argc和argv含义
  6. 关于WPF中Popup控件的小记
  7. CVPR读书笔记[5]:Gabor特征提取之Gabor核的实现
  8. USACO Section 2.1 Sorting a Three-Valued Sequence
  9. HTML之学习笔记(一)简介
  10. ElasticSearch(6)-结构化查询
  11. CSS行高line-height的一些深入理解及应用
  12. 【转】10款GitHub上最火爆的国产开源项目
  13. ZeroMQ 教程 002 : 高级技巧
  14. java 安装教程
  15. .Net高级进阶,教你如何构建企业模型数据拦截层,动态控制字段验证
  16. 大规模数据导入和导出(oracle)
  17. Flask-WTF表单的使用
  18. Iterator和Iterable的区别以及使用
  19. python --- 10 *args **kwargs 命名空间 作用域 函数的嵌套
  20. Materialize和Material Design Lite的区别

热门文章

  1. javascript typeof()的用法与运算符用法
  2. django模板templates详解(二)
  3. Linux(Ubuntu) 常用命令
  4. 让ADO.NET Entity Framework 支持ACCESS数据库
  5. OC 内存管理(retain和release)
  6. 如何解决“请考虑使用 app.config 将程序集“XXXXXXXX”从版本XXXX重新映射到版本XXXX”的问题
  7. 访问google的若干解决办法
  8. maven学习记录二——依赖管理
  9. java连接数据库(sqlserver和mysql)
  10. Ueditor插入script标签