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 相关文章推荐
让你同时上传 1000 个文件 (二)
Oct 09 PHP
php中Smarty模板初体验
Aug 08 PHP
thinkphp特殊标签用法概述
Nov 24 PHP
PHP实现恶意DDOS攻击避免带宽占用问题方法
May 27 PHP
ThinkPHP模型详解
Jul 27 PHP
php简单创建zip压缩文件的方法
Apr 30 PHP
PHP处理数组和XML之间的互相转换
Jun 02 PHP
CI框架封装的常用图像处理方法(缩略图,水印,旋转,上传等)
Nov 22 PHP
PHP中ajax无刷新上传图片与图片下载功能
Feb 21 PHP
php使用 readfile() 函数设置文件大小大小的方法
Aug 11 PHP
PHP基于redis计数器类定义与用法示例
Feb 08 PHP
PHP中isset、empty的用法与区别示例详解
Nov 05 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
使用sockets:从新闻组中获取文章(三)
2006/10/09 PHP
ThinkPHP3.0略缩图不能保存到子目录的解决方法
2012/09/30 PHP
php生成0~1随机小数的方法(必看)
2017/04/05 PHP
Laravel 微信小程序后端实现用户登录的示例代码
2019/11/26 PHP
雄兵连第三季海报曝光,艾妮熙德成主角,蔷薇新造型
2021/03/09 国漫
JavaScript去除空格的几种方法
2006/10/03 Javascript
解决AJAX中跨域访问出现'没有权限'的错误
2008/08/20 Javascript
javascript 硬盘序列号+其它硬件信息
2008/12/23 Javascript
原始的js代码和jquery对比体会
2013/09/10 Javascript
js插件方式打开pdf文件(浏览器pdf插件分享)
2013/12/20 Javascript
javascript实现动态统计图开发实例
2015/11/21 Javascript
jQuery插件EasyUI校验规则 validatebox验证框
2015/11/29 Javascript
a标签跳转到指定div,jquery添加和移除class属性的实现方法
2016/10/10 Javascript
详解angular ui-grid之过滤器设置
2017/06/07 Javascript
angular或者js怎么确定选中ul中的哪几个li
2017/08/16 Javascript
基于zepto.js实现登录界面
2017/10/09 Javascript
JS/HTML5游戏常用算法之碰撞检测 包围盒检测算法详解【圆形情况】
2018/12/13 Javascript
python list元素为tuple时的排序方法
2018/04/18 Python
Python 实现子类获取父类的类成员方法
2019/01/11 Python
python自动发送测试报告邮件功能的实现
2019/01/22 Python
Python检测数据类型的方法总结
2019/05/20 Python
django 多数据库及分库实现方式
2020/04/01 Python
python 实现PIL模块在图片画线写字
2020/05/16 Python
html5本地存储之localstorage 、本地数据库、sessionStorage简单使用示例
2014/05/08 HTML / CSS
GUESS德国官网:美国牛仔服装品牌
2017/02/14 全球购物
销售总监工作职责
2013/11/21 职场文书
文明寝室申报材料
2014/05/12 职场文书
银行求职信怎么写
2014/05/26 职场文书
尊老爱幼演讲稿
2014/09/04 职场文书
部队2015年终工作总结
2015/04/02 职场文书
汽车4S店前台接待岗位职责
2015/04/03 职场文书
2015年小学一年级班主任工作总结
2015/05/21 职场文书
爱国主义影片观后感
2015/06/18 职场文书
六种css3实现的边框过渡效果
2021/04/22 HTML / CSS
MySQL Router的安装部署
2021/04/24 MySQL
hive数据仓库新增字段方法
2022/06/25 数据库