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获取网络上文件
Oct 09 PHP
Php Ctemplate引擎开发相关内容
Mar 03 PHP
解析PHP中ob_start()函数的用法
Jun 24 PHP
php获取qq用户昵称和在线状态(实例分析)
Oct 27 PHP
PHP6 中可能会出现的新特性预览
Apr 04 PHP
PHP实现的sqlite数据库连接类
Dec 12 PHP
PHP中Session可能会引起并发问题
Jun 26 PHP
浅谈PHP值mysql操作类
Jun 29 PHP
PHP云打印类完整示例
Oct 15 PHP
PHP 结合 Boostrap 结合 js 实现学生列表删除编辑及搜索功能
May 21 PHP
Thinkphp5.0框架视图view的循环标签用法示例
Oct 12 PHP
禁止直接访问php文件代码分享
May 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
百度站点地图(百度sitemap)生成方法分享
2014/01/09 PHP
php array_merge函数使用需要注意的一个问题
2015/03/30 PHP
PHP下的浮点运算不准的解决方法
2016/10/27 PHP
jquery Mobile入门—多页面切换示例学习
2013/01/08 Javascript
JQuery入门——移除绑定事件unbind方法概述及应用
2013/02/05 Javascript
jQuery 的全选(全非选)即取得被选中的值使用介绍
2013/11/12 Javascript
单击和双击事件的冲突处理示例代码
2014/04/03 Javascript
我的Node.js学习之路(三)--node.js作用、回调、同步和异步代码 以及事件循环
2014/07/06 Javascript
JavaScript使用focus()设置焦点失败的解决方法
2014/09/03 Javascript
JavaScript将Web页面内容导出到Word及Excel的方法
2015/02/13 Javascript
jQuery实现连续动画效果实例分析
2015/10/09 Javascript
谈一谈javascript闭包
2016/01/28 Javascript
AngularJS基础 ng-src 指令简单示例
2016/08/03 Javascript
jQuery实现加入收藏夹功能(主流浏览器兼职)
2016/12/24 Javascript
完美解决手机浏览器顶部下拉出现网页源或刷新的问题
2017/11/30 Javascript
微信小程序wx.previewImage预览图片实例详解
2017/12/07 Javascript
JS实现字符串去重及数组去重的方法示例
2018/04/21 Javascript
工作中常用到的ES6语法
2018/09/04 Javascript
VUEX采坑之路之获取不到$store的解决方法
2019/11/08 Javascript
详解React 元素渲染
2020/07/07 Javascript
查找Vue中下标的操作(some和findindex)
2020/08/12 Javascript
由浅入深讲解python中的yield与generator
2017/04/05 Python
python 重定向获取真实url的方法
2018/05/11 Python
Python实用技巧之利用元组代替字典并为元组元素命名
2018/07/11 Python
如何运行.ipynb文件的图文讲解
2019/06/27 Python
Pycharm新建模板默认添加个人信息的实例
2019/07/15 Python
python3实现网页版raspberry pi(树莓派)小车控制
2020/02/12 Python
Python实现捕获异常发生的文件和具体行数
2020/04/25 Python
matplotlib 使用 plt.savefig() 输出图片去除旁边的空白区域
2021/01/05 Python
门卫人员岗位职责
2013/12/24 职场文书
恶搞卫生巾广告词
2014/03/18 职场文书
大学英语演讲稿范文
2014/04/24 职场文书
2014年乡镇领导个人整改措施
2014/09/19 职场文书
2016年党课培训学习心得体会
2016/01/07 职场文书
2019年怎样才能撰写出优秀的自荐信
2019/03/25 职场文书
HTML5 新增内容和 API详解
2021/11/17 HTML / CSS