php使用lua+redis实现限流,计数器模式,令牌桶模式


Posted in PHP onApril 04, 2019

lua 优点

减少网络开销: 不使用 Lua 的代码需要向 Redis 发送多次请求, 而脚本只需一次即可, 减少网络传输;

原子操作: Redis 将整个脚本作为一个原子执行, 无需担心并发, 也就无需事务;

复用: 脚本会永久保存 Redis 中, 其他客户端可继续使用.

计数器模式:

利用lua脚本一次性完成处理达到原子性,通过INCR自增计数,判断是否达到限定值,达到限定值则返回限流,添加key过期时间应该范围过度

$lua = '
        local i = redis.call("INCR", KEYS[1]) 
        if i > 10 then
          return "wait"
        else
          if i == 1
          then
            redis.call("expire", KEYS[1], KEYS[2])
          end
          return redis.call("get", KEYS[3])
        end
      ';

laravel 请求代码:

Redis::eval($lua, 3, sprintf(RedisKey::API_LIMIT, $key, $callService['service']), 60, $cache_key);

令牌桶模式

每次请求在桶内拿取一个令牌,有令牌则通过,否则返回,并且按照算法一定的慢慢把令牌放入桶内

$lua = '
        local data = redis.call("get", KEYS[2])
        if data then
        
          local dataJson = cjson.decode(data)
          local newNum = math.min(KEYS[3], math.floor(((dataJson["limitVal"] - 1) + (KEYS[3]/KEYS[5]) * (KEYS[4] - dataJson["limitTime"]))))
          
          if newNum > 0 then
          
            local paramsJson = cjson.encode({limitVal=newNum,limitTime=KEYS[4]})
            redis.call("set", KEYS[2], paramsJson)
            return redis.call("get", KEYS[1])
          
          end
           return "wait"
        end
        
        local paramsJson = cjson.encode({limitVal=KEYS[3],limitTime=KEYS[4]})
        redis.call("set", KEYS[2], paramsJson)
        return redis.call("get", KEYS[1])
      ';
      
      // 1. lua脚本, 2 KEYS数量, 3 查找数据key, 4 限制key, 5 桶内数量, 6 时间戳, 7 过期时间
      Redis::eval(1,2,3,4,5,6,7参数);

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
PHP与已存在的Java应用程序集成
Oct 09 PHP
PHP Mysql编程之高级技巧
Aug 27 PHP
php调用dll的实例操作动画与代码分享
Aug 14 PHP
PHP数据类型之整数类型、浮点数的介绍
Apr 28 PHP
关于PHP模板Smarty的初级使用方法以及心得分享
Jun 21 PHP
smarty简单入门实例
Nov 28 PHP
php注册登录系统简化版
Dec 28 PHP
Yii2 RESTful中api的使用及开发实例详解
Jul 06 PHP
Laravel模型间关系设置分表的方法示例
Apr 21 PHP
PHP格式化显示时间date()函数代码
Oct 03 PHP
浅谈laravel5.5 belongsToMany自身的正确用法
Oct 17 PHP
PHP如何通过date() 函数格式化显示时间
Nov 13 PHP
PHP设计模式之策略模式原理与用法实例分析
Apr 04 #PHP
Laravel路由研究之domain解决多域名问题的方法示例
Apr 04 #PHP
PHP设计模式之观察者模式定义与用法分析
Apr 04 #PHP
PHP示例演示发送邮件给某个邮箱
Apr 03 #PHP
PHP whois查询类定义与用法示例
Apr 03 #PHP
ThinkPHP3.2.3框架实现的空模块、空控制器、空操作,跳转到错误404页面图文详解
Apr 03 #PHP
PHP反射实际应用示例
Apr 03 #PHP
You might like
DOTA2 探索永无止境 玩家自创强悍插眼攻略
2020/04/20 DOTA
乱谈我对耳机、音箱的感受
2021/03/02 无线电
基于PHP异步执行的常用方式详解
2013/06/03 PHP
php微信开发之带参数二维码的使用
2016/08/03 PHP
Jquery+ajax请求data显示在GridView上(asp.net)
2010/08/27 Javascript
jquery常用技巧及常用方法列表集合
2011/04/06 Javascript
json的前台操作和后台操作实现代码
2012/01/20 Javascript
jQuery+css+html实现页面遮罩弹出框
2013/03/21 Javascript
js中arguments,caller,callee,apply的用法小结
2014/01/28 Javascript
Express作者TJ告别Node.js奔向Go
2014/07/14 Javascript
express的中间件cookieParser详解
2014/12/04 Javascript
jquery滚动加载数据的方法
2015/03/09 Javascript
js+css实现有立体感的按钮式文字竖排菜单效果
2015/09/01 Javascript
Javascript 字符串模板的简单实现
2016/02/13 Javascript
JS与HTML结合实现流程进度展示条思路详解
2017/09/03 Javascript
Vue中使用vux配置代码详解
2018/09/16 Javascript
jQuery层叠选择器用法实例分析
2019/06/28 jQuery
JavaScript之scrollTop、scrollHeight、offsetTop、offsetHeight等属性学习笔记
2020/07/15 Javascript
[07:47]DOTA2国际邀请赛采访专栏:探访Valve总部
2013/08/08 DOTA
[02:30]联想杯DOTA2完美世界全国高校联赛—北京站现场
2015/11/16 DOTA
[08:40]Navi Vs Newbee
2018/06/07 DOTA
网站渗透常用Python小脚本查询同ip网站
2017/05/08 Python
python数据预处理之将类别数据转换为数值的方法
2017/07/05 Python
python对html过滤处理的方法
2018/10/21 Python
使用pycharm在本地开发并实时同步到服务器
2019/08/02 Python
巧用HTML5给按钮背景设计不同的动画简单实例
2016/08/09 HTML / CSS
AmazeUI导航的示例代码
2020/08/14 HTML / CSS
匡威德国官网:Converse德国
2019/01/26 全球购物
Wiggle澳大利亚:自行车、跑步、游泳商店
2020/11/07 全球购物
毕业生找工作的自我评价
2013/10/18 职场文书
机械设计毕业生自荐信
2014/02/02 职场文书
2014幼儿园保育员工作总结
2014/11/10 职场文书
2015年个人实习工作总结
2014/12/12 职场文书
史上最牛辞职信
2015/05/13 职场文书
表扬稿表扬信的格式及范文
2019/06/24 职场文书
在python中实现导入一个需要传参的模块
2021/05/12 Python