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正确配置mysql(apache环境)
Aug 28 PHP
PHP gbk环境下json_dencode传送来的汉字
Nov 13 PHP
php ci框架验证码实例分析
Jun 26 PHP
php+js iframe实现上传头像界面无跳转
Apr 29 PHP
编写PHP脚本清除WordPress头部冗余代码的方法讲解
Mar 01 PHP
Yii2中cookie用法示例分析
Jul 18 PHP
thinkphp配置文件路径的实现方法
Aug 30 PHP
php实现HTML实体编号与非ASCII字符串相互转换类实例
Nov 02 PHP
php each 返回数组中当前的键值对并将数组指针向前移动一步实例
Nov 22 PHP
php基于协程实现异步的方法分析
Jul 17 PHP
php+layui数据表格实现数据分页渲染代码
Oct 26 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 上传文件类型判断函数(避免上传漏洞 )
2010/06/08 PHP
thinkphp中AJAX返回ajaxReturn()方法分析
2016/12/06 PHP
toString()一个会自动调用的方法
2010/02/08 Javascript
Zero Clipboard js+swf实现的复制功能使用方法
2010/03/07 Javascript
JavaScript 图像动画的小demo
2012/05/23 Javascript
Javascript实现页面跳转的几种方式分享
2013/10/26 Javascript
jQuery获得内容和属性方法及示例
2013/12/02 Javascript
js 实现的可折叠留言板(附源码下载)
2014/07/01 Javascript
jQuery中ajax的post()方法用法实例
2014/12/26 Javascript
JavaScript中for循环的使用详解
2015/06/03 Javascript
JavaScript中函数(Function)的apply与call理解
2015/07/08 Javascript
jQuery满屏焦点图左右滚动特效代码分享
2015/09/07 Javascript
jQuery实现的checkbox级联选择下拉菜单效果示例
2016/12/26 Javascript
Angular.js中ng-if、ng-show和ng-hide的区别介绍
2017/01/20 Javascript
详解如何将 Vue-cli 改造成支持多页面的 history 模式
2017/11/20 Javascript
Vue.directive使用注意(小结)
2018/08/31 Javascript
Vue开发中遇到的跨域问题及解决方法
2020/02/11 Javascript
vue常用高阶函数及综合实例
2021/02/25 Vue.js
[02:11]DOTA2上海特级锦标赛主赛事第二日RECAP
2016/03/04 DOTA
使用Python抓取模板之家的CSS模板
2015/03/16 Python
解决Python安装后pip不能用的问题
2018/06/12 Python
详解python selenium 爬取网易云音乐歌单名
2019/03/28 Python
详解python opencv、scikit-image和PIL图像处理库比较
2019/12/26 Python
Python使用urllib模块对URL网址中的中文编码与解码实例详解
2020/02/18 Python
简单介绍CSS3中Media Query的使用
2015/07/07 HTML / CSS
诗狄娜化妆品官方网站:Stila Cosmetics
2016/12/21 全球购物
会计与出纳自荐书范文
2014/03/16 职场文书
房屋租房协议书范本
2014/12/04 职场文书
优秀大学生事迹材料
2014/12/24 职场文书
2015年国际护士节演讲稿
2015/03/18 职场文书
2015年司机年终工作总结
2015/05/14 职场文书
婚礼父母致辞
2015/07/28 职场文书
2019秋季运动会口号
2019/06/25 职场文书
《悲惨世界》:比天空更广阔的是人的心灵
2020/01/16 职场文书
html css3不拉伸图片显示效果
2021/06/07 HTML / CSS
java版 简单三子棋游戏
2022/05/04 Java/Android