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 相关文章推荐
Windows 下的 PHP-PEAR 安装方法
Nov 20 PHP
PHP include_path设置技巧分享
Jul 03 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(五)
Jun 23 PHP
PHP文件锁定写入实例解析
Jul 14 PHP
PHP实现即时输出、实时输出内容方法
May 27 PHP
php 生成签名及验证签名详解
Oct 26 PHP
php批量删除操作(数据访问)
May 23 PHP
PHP中如何使用Redis接管文件存储Session详解
Nov 28 PHP
PDO::exec讲解
Jan 28 PHP
php 实现银联商务H5支付的示例代码
Oct 12 PHP
Yii框架Session与Cookie使用方法示例
Oct 14 PHP
php的lavarel框架中join和orWhere的用法
Dec 28 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 session和cookie使用说明
2010/04/07 PHP
PHP执行linux系统命令的常用函数使用说明
2010/04/27 PHP
二招解决php乱码问题
2012/03/25 PHP
PHP_Cooikes不同页面无法传递的解决方法
2014/03/07 PHP
php及codeigniter使用session-cookie的方法(详解)
2017/04/06 PHP
Yii 2.0自带的验证码使用经验分享
2017/06/19 PHP
laravel 实现向公共模板中传值 (view composer)
2019/10/22 PHP
PhpStorm 2020.3:新增开箱即用的PHP 8属性(推荐)
2020/10/30 PHP
JS实现打开本地文件或文件夹
2021/03/09 Javascript
如何实现浏览器上的右键菜单
2006/07/10 Javascript
Js 弹出框口并返回值的两种常用方法
2010/12/30 Javascript
jquery获取radio值(单选组radio)
2014/10/16 Javascript
js实现圆盘记速表
2015/08/03 Javascript
jquery+ajax实现省市区三级联动效果简单示例
2017/01/04 Javascript
ES6实现的遍历目录函数示例
2017/04/07 Javascript
Node做中转服务器转发接口
2017/10/18 Javascript
React 源码中的依赖注入方法
2018/11/07 Javascript
node链接mongodb数据库的方法详解【阿里云服务器环境ubuntu】
2019/03/07 Javascript
vue使用微信JS-SDK实现分享功能
2019/08/23 Javascript
Python使用shelve模块实现简单数据存储的方法
2015/05/20 Python
Python IDE PyCharm的基本快捷键和配置简介
2015/11/04 Python
Python读取一个目录下所有目录和文件的方法
2016/07/15 Python
Python文本相似性计算之编辑距离详解
2016/11/28 Python
对numpy中shape的深入理解
2018/06/15 Python
解决Python pandas plot输出图形中显示中文乱码问题
2018/12/12 Python
Django之编辑时根据条件跳转回原页面的方法
2019/08/21 Python
Python表达式的优先级详解
2020/02/18 Python
python 线性回归分析模型检验标准--拟合优度详解
2020/02/24 Python
python中resample函数实现重采样和降采样代码
2020/02/25 Python
中学教师管理制度
2014/01/14 职场文书
大学军训的体会
2014/11/08 职场文书
2014年内勤工作总结
2014/11/24 职场文书
体育教师个人总结
2015/02/09 职场文书
用python开发一款操作MySQL的小工具
2021/05/12 Python
浅谈Python协程asyncio
2021/06/20 Python
Python中Matplotlib的点、线形状、颜色以及绘制散点图
2022/04/07 Python