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 相关文章推荐
基于mysql的论坛(6)
Oct 09 PHP
从MySQL数据库表中取出随机数据的代码
Sep 05 PHP
php在线打包程序源码
Jul 27 PHP
php 代码优化的42条建议 推荐
Sep 25 PHP
php dirname(__FILE__) 获取当前文件的绝对路径
Jun 28 PHP
php中get_headers函数的作用及用法的详细介绍
Apr 27 PHP
使用php 获取时间今天明天昨天时间戳的详解
Jun 20 PHP
php cookie使用方法学习笔记分享
Nov 07 PHP
PHP中的闭包(匿名函数)浅析
Feb 07 PHP
php实现对两个数组进行减法操作的方法
Apr 17 PHP
php并发加锁示例
Oct 17 PHP
PHP模版引擎原理、定义与用法实例
Mar 29 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
Laravel修改验证提示信息为中文的示例
2019/10/23 PHP
js left,right,mid函数
2008/06/10 Javascript
jquery HotKeys轻松搞定键盘事件代码
2008/08/30 Javascript
JS函数this的用法实例分析
2015/02/05 Javascript
jQuery简单实现图片预加载
2015/04/20 Javascript
JS中字符串trim()使用示例
2015/05/26 Javascript
vue引入ueditor及node后台配置详解
2018/01/03 Javascript
electron 安装,调试,打包的具体使用
2019/11/06 Javascript
微信小程序间使用navigator跳转传值问题实例分析
2020/03/27 Javascript
原生js滑动轮播封装
2020/07/31 Javascript
[01:12]DOTA2次级职业联赛 - Newbee.Y 战队宣传片
2014/12/01 DOTA
Python3.x版本中新的字符串格式化方法
2015/04/24 Python
python目录与文件名操作例子
2016/08/28 Python
matplotlib作图添加表格实例代码
2018/01/23 Python
Python File(文件) 方法整理
2019/02/18 Python
python爬虫租房信息在地图上显示的方法
2019/05/13 Python
Python3实现汉语转换为汉语拼音
2019/07/08 Python
python实现代码统计程序
2019/09/19 Python
pytorch 计算Parameter和FLOP的操作
2021/03/04 Python
CSS3实现闪烁动画效果的方法
2015/02/09 HTML / CSS
使用html2canvas实现浏览器截图的示例代码
2018/01/26 HTML / CSS
HTML5实现音频和视频嵌入的方法
2018/08/22 HTML / CSS
html5 拖拽及用 js 实现拖拽功能的示例代码
2020/10/23 HTML / CSS
美国现代家具网站:Design Within Reach
2018/07/19 全球购物
三星新西兰官网:Samsung新西兰
2019/03/05 全球购物
山海经纬软件测试笔试题和面试题
2013/04/02 面试题
国外软件测试工程师面试题
2016/12/09 面试题
全陪导游欢迎词
2014/01/17 职场文书
上课说话检讨书大全
2014/01/22 职场文书
园林系毕业生求职信
2014/06/23 职场文书
2016年春季运动会加油稿
2015/07/22 职场文书
2019通用版劳动合同范本!
2019/07/11 职场文书
一篇文章带你学习Mybatis-Plus(新手入门)
2021/08/02 Java/Android
一文了解JavaScript用Element Traversal新属性遍历子元素
2021/11/27 Javascript
Python FuzzyWuzzy实现模糊匹配
2022/04/28 Python
在容器中使用nginx搭建上传下载服务器
2022/05/11 Servers