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 相关文章推荐
建立动态的WML站点(三)
Oct 09 PHP
centos 5.6 升级php到5.3的方法
May 14 PHP
PHP代码网站如何防范SQL注入漏洞攻击建议分享
Mar 01 PHP
用PHP即时捕捉PHP中的错误并发送email通知的实现代码
Jan 19 PHP
PHP 类相关函数的使用详解
May 10 PHP
PHP制作图形验证码代码分享
Oct 23 PHP
PHP中返回引用类型的方法
Apr 03 PHP
PHP实现C#山寨ArrayList的方法
Jul 16 PHP
yii实现使用CUploadedFile上传文件的方法
Dec 28 PHP
CodeIgniter 完美解决URL含有中文字符串
May 13 PHP
PHP基于反射机制实现插件的可插拔设计详解
Nov 10 PHP
PHP模糊查询技术实例分析【附源码下载】
Mar 07 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
PHP与MySQL开发中页面乱码的产生与解决
2008/03/27 PHP
使用PHP获取网络文件的实现代码
2010/01/01 PHP
ubuntu12.04使用c编写php扩展模块教程分享
2013/12/25 PHP
PHP中使用sleep造成mysql读取失败的案例和解决方法
2014/08/21 PHP
PHP使用GD库制作验证码的方法(点击验证码或看不清会刷新验证码)
2017/08/15 PHP
网页自动跳转代码收集
2009/09/27 Javascript
用表格输出1-1000之间的数字实现代码(附特效)
2013/04/21 Javascript
使用JS取得焦点(focus)元素代码
2014/03/22 Javascript
javascript中 try catch用法
2015/08/16 Javascript
js实现下拉列表选中某个值的方法(3种方法)
2015/12/17 Javascript
浅谈Sticky组件的改进实现
2016/03/22 Javascript
jQuery leonaScroll 1.1 自定义滚动条插件(推荐)
2016/09/17 Javascript
简单的js计算器实现
2016/10/26 Javascript
[原创]jQuery实现合并/追加数组并去除重复项的方法
2018/04/11 jQuery
vue router动态路由下让每个子路由都是独立组件的解决方案
2018/04/24 Javascript
JavaScript时间日期操作实例小结【5个示例】
2018/12/22 Javascript
使用typescript改造koa开发框架的实现
2020/02/04 Javascript
JS实现公告上线滚动效果
2021/01/10 Javascript
[02:46]2014DOTA2国际邀请赛 选手为你解读比赛MVP充满梦想
2014/07/09 DOTA
Python入门篇之文件
2014/10/20 Python
Nginx搭建HTTPS服务器和强制使用HTTPS访问的方法
2015/08/16 Python
Flask框架Flask-Login用法分析
2018/07/23 Python
详解Appium+Python之生成html测试报告
2019/01/04 Python
python画双y轴图像的示例代码
2019/07/07 Python
python编写简单端口扫描器
2019/09/04 Python
python游戏开发的五个案例分享
2020/03/09 Python
matplotlib 曲线图 和 折线图 plt.plot()实例
2020/04/17 Python
Pycharm连接gitlab实现过程图解
2020/09/01 Python
理货员的岗位职责
2013/11/23 职场文书
电脑教师的自我评价
2013/12/18 职场文书
个人查摆剖析材料
2014/10/16 职场文书
酒店采购员岗位职责
2015/04/03 职场文书
硕士论文致谢范文
2015/05/14 职场文书
python实战之90行代码写个猜数字游戏
2021/04/22 Python
MySQL高速缓存启动方法及参数详解(query_cache_size)
2021/07/01 MySQL
详解Spring Bean的配置方式与实例化
2022/06/10 Java/Android