Redis Lua脚本实现ip限流示例


Posted in Redis onJuly 15, 2022

引言

分布式限流最关键的是要将限流服务做成原子化,而解决方案可以使使用redis+lua或者nginx+lua技术进行实现,通过这两种技术可以实现的高并发和高性能。
首先我们来使用redis+lua实现时间窗内某个接口的请求数限流,实现了该功能后可以改造为限流总并发/请求数和限制总资源数。Lua本身就是一种编程语言,也可以使用它实现复杂的令牌桶或漏桶算法。
如下操作因是在一个lua脚本中(相当于原子操作),又因Redis是单线程模型,因此是线程安全的。

相比Redis事务来说,Lua脚本有以下优点

减少网络开销: 不使用 Lua 的代码需要向 Redis 发送多次请求, 而脚本只需一次即可, 减少网络传输;
原子操作: Redis 将整个脚本作为一个原子执行, 无需担心并发, 也就无需事务;
复用: 脚本会永久保存 Redis 中, 其他客户端可继续使用.

Lua脚本

local key = KEYS[1] --限流KEY(一秒一个)
local limit = tonumber(ARGV[1]) --限流大小
local current = tonumber(redis.call('get', key) or "0")
if current + 1 > limit then --如果超出限流大小
    return 0
else --请求数+1,并设置2秒过期
    redis.call("INCRBY", key,"1")
    redis.call("expire", key,"2")
end
return 1

java代码

import org.apache.commons.io.FileUtils;
import redis.clients.jedis.Jedis;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
public class RedisLimitRateWithLUA {
    public static void main(String[] args) {
        final CountDownLatch latch = new CountDownLatch(1);
        for (int i = 0; i < 7; i++) {
            new Thread(new Runnable() {
                public void run() {
                    try {
                        latch.await();
                        System.out.println("请求是否被执行:"+accquire());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
        latch.countDown();
    }
    public static boolean accquire() throws IOException, URISyntaxException {
        Jedis jedis = new Jedis("127.0.0.1");
        File luaFile = new File(RedisLimitRateWithLUA.class.getResource("/").toURI().getPath() + "limit.lua");
        String luaScript = FileUtils.readFileToString(luaFile);
        String key = "ip:" + System.currentTimeMillis()/1000; // 当前秒
        String limit = "5"; // 最大限制
        List<String> keys = new ArrayList<String>();
        keys.add(key);
        List<String> args = new ArrayList<String>();
        args.add(limit);
        Long result = (Long)(jedis.eval(luaScript, keys, args)); // 执行lua脚本,传入参数
        return result == 1;
    }
}

运行结果

请求是否被执行:true
请求是否被执行:true
请求是否被执行:false
请求是否被执行:true
请求是否被执行:true
请求是否被执行:true
请求是否被执行:fals

从结果可看出只有5个请求成功执行

IP限流Lua脚本

local key = "rate.limit:" .. KEYS[1]
local limit = tonumber(ARGV[1])
local expire_time = ARGV[2]
local is_exists = redis.call("EXISTS", key)
if is_exists == 1 then
    if redis.call("INCR", key) > limit then
        return 0
    else
        return 1
    end
else
    redis.call("SET", key, 1)
    redis.call("EXPIRE", key, expire_time)
    return 1
end

以上就是Redis Lua脚本实现ip限流示例的详细内容,更多关于Redis Lua限流的资料请关注三水点靠木其它相关文章!


Tags in this post...

Redis 相关文章推荐
基于Redis过期事件实现订单超时取消
May 08 Redis
基于Redis延迟队列的实现代码
May 13 Redis
详解redis分布式锁的这些坑
May 19 Redis
Django使用redis配置缓存的方法
Jun 01 Redis
浅析Redis Sentinel 与 Redis Cluster
Jun 24 Redis
Redis 常见使用场景
Aug 30 Redis
Redis三种集群模式详解
Oct 05 Redis
SpringBoot整合Redis入门之缓存数据的方法
Nov 17 Redis
分布式Redis Cluster集群搭建与Redis基本用法
Feb 24 Redis
Redis 异步机制
May 15 Redis
Redis基本数据类型String常用操作命令
Jun 01 Redis
redis protocol通信协议及使用详解
Jul 15 #Redis
Redis sentinel哨兵集群的实现步骤
Jul 15 #Redis
Redis唯一ID生成器的实现
Jul 07 #Redis
Redis+AOP+自定义注解实现限流
Jun 28 #Redis
利用Redis实现点赞功能的示例代码
Jun 28 #Redis
一文教你快速生成MySQL数据库关系图
Jun 28 #Redis
Redis实现主从复制方式(Master&Slave)
Jun 21 #Redis
You might like
PHP DataGrid 实现代码
2009/08/12 PHP
CI框架中cookie的操作方法分析
2014/12/12 PHP
php封装实现钉钉机器人报警接口的示例代码
2020/08/08 PHP
javascript 贪吃蛇实现代码
2008/11/22 Javascript
Flash图片上传组件 swfupload使用指南
2015/03/14 Javascript
js检测用户输入密码强度
2015/10/22 Javascript
学习JavaScript设计模式(策略模式)
2015/11/26 Javascript
javascript实现拖放效果
2015/12/16 Javascript
JS基于ocanvas插件实现的简单画板效果代码(附demo源码下载)
2016/04/05 Javascript
使用vue.js2.0 + ElementUI开发后台管理系统详细教程(二)
2017/01/21 Javascript
使用get方式提交表单在地址栏里面不显示提交信息
2017/02/21 Javascript
Node.js使用Angular简单示例
2018/05/11 Javascript
基于Vue2-Calendar改进的日历组件(含中文使用说明)
2019/04/14 Javascript
js实现图片跟随鼠标移动效果
2019/10/16 Javascript
原生js+canvas实现贪吃蛇效果
2020/08/02 Javascript
vue集成一个支持图片缩放拖拽的富文本编辑器
2021/01/29 Vue.js
[02:25]专访DOTA2负责人Erik 国际邀请赛暂不会离开西雅
2014/07/21 DOTA
学习python处理python编码问题
2011/03/13 Python
Python三种遍历文件目录的方法实例代码
2018/01/19 Python
对python使用http、https代理的实例讲解
2018/05/07 Python
Python 3.x 判断 dict 是否包含某键值的实例讲解
2018/07/06 Python
python 为什么说eval要慎用
2019/03/26 Python
Python实现获取当前目录下文件名代码详解
2020/03/10 Python
Keras: model实现固定部分layer,训练部分layer操作
2020/06/28 Python
Python使用tkinter实现小时钟效果
2021/02/22 Python
html5 http的轮询和Websocket原理
2018/10/19 HTML / CSS
英国第一的购买便宜玩具和游戏的在线购物网站:Bargain Max
2018/01/24 全球购物
数控技术专科生自我评价
2014/01/08 职场文书
乡镇网格化管理实施方案
2014/03/23 职场文书
纪律教育学习心得体会
2014/09/02 职场文书
民政局副局长民主生活会个人对照检查材料
2014/09/19 职场文书
护林员个人总结
2015/03/04 职场文书
青年岗位能手事迹材料(2016推荐版)
2016/03/01 职场文书
python实现简单倒计时功能
2021/04/21 Python
Anaconda安装pytorch和paddle的方法步骤
2022/04/03 Python
微信告警的zabbix监控系统 监控整个NGINX集群
2022/04/18 Servers