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 相关文章推荐
一键删除顽固的空文件夹 软件下载
Jan 26 PHP
php array_map array_multisort 高效处理多维数组排序
Jun 11 PHP
php whois查询API制作方法
Jun 23 PHP
单点登录 Ucenter示例分析
Oct 29 PHP
php读取csv文件并输出的方法
Mar 14 PHP
CodeIgniter读写分离实现方法详解
Jan 20 PHP
php实现博客,论坛图片防盗链的方法
Oct 15 PHP
php中10个不同等级压缩优化图片操作示例
Nov 14 PHP
PHP迭代与递归实现无限级分类
Aug 28 PHP
php-msf源码详解
Dec 25 PHP
PHP实现批量修改文件名的方法示例
Sep 18 PHP
PHP实现单条sql执行多个数据的insert语句方法
Oct 11 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
Terran魔法科技
2020/03/14 星际争霸
PHP开发文件系统实例讲解
2006/10/09 PHP
使用网络地址转换实现多服务器负载均衡
2006/10/09 PHP
php Static关键字实用方法
2010/06/04 PHP
解析crontab php自动运行的方法
2013/06/24 PHP
PHP使用JSON和将json还原成数组
2015/02/12 PHP
php统计数组元素个数的方法
2015/07/02 PHP
DOM Scripting中的图片切换[兼容Firefox]
2010/06/12 Javascript
JS获取页面窗口大小的代码解读
2011/12/01 Javascript
在JS中解析HTML字符串示例代码
2014/04/16 Javascript
jQuery处理图片加载失败的常用方法
2015/06/08 Javascript
jQuery实现本地预览上传图片功能
2016/01/08 Javascript
AngularJS定时器的使用与移除操作方法【interval与timeout】
2016/12/14 Javascript
Angular.JS中select下拉框设置value的方法
2017/06/20 Javascript
Angular.js中数组操作的方法教程
2017/07/31 Javascript
微信小程序出现wx.navigateTo页面不跳转问题的解决方法
2017/12/26 Javascript
React项目动态设置title标题的方法示例
2018/09/26 Javascript
详解如何快速配置webpack多入口脚手架
2018/12/28 Javascript
详解VUE单页应用骨架屏方案
2019/01/17 Javascript
jquery 验证用户名是否重复代码实例
2019/05/14 jQuery
深入浅出了解Node.js Streams
2019/05/27 Javascript
浅谈Vue.use到底是什么鬼
2020/01/21 Javascript
python获得图片base64编码示例
2014/01/16 Python
Python中使用第三方库xlrd来写入Excel文件示例
2015/04/05 Python
Python开发的实用计算器完整实例
2017/05/10 Python
Python画图实现同一结点多个柱状图的示例
2019/07/07 Python
python3实现单目标粒子群算法
2019/11/14 Python
浅谈Python程序的错误:变量未定义
2020/06/02 Python
Java面试题汇总
2015/12/06 面试题
蔬菜基地的创业计划书
2014/01/06 职场文书
文明青少年标兵事迹材料
2014/01/28 职场文书
文案策划求职信
2014/03/18 职场文书
IT工程师岗位职责
2014/07/04 职场文书
离婚纠纷代理词
2015/05/23 职场文书
2015年小学数学教师个人工作总结
2015/05/25 职场文书
nginx作grpc的反向代理踩坑总结
2021/07/07 Servers