首页 > 数据库 >redis+lua脚本实现接口限流

redis+lua脚本实现接口限流

时间:2024-04-19 09:56:53浏览次数:22  
标签:脚本 return Lua redis lua 限流 key

写在前面

在多线程的情况下对一个接口进行访问,如果访问次数过大,且没有缓存存在的情况下大量的请求打到数据库可能会存在数据库宕机,从而造成服务的不可用性。往往我们需要对其进行限流操作用来保证服务的高可用性,以下介绍下redis限流如何使用。

lua脚本

Lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。Lua 本身并没有提供对于原子性的直接支持,它只是一种脚本语言,通常是嵌入到其他宿主程序中运行,比如Redis。 在Redis中,执行Lua脚本的原子性是指:整个Lua脚本在执行期间,不会被其他客户端的命令打断。

特性

  • 轻量级:它用标准C语言编写并以源代码形式开放,编译后仅仅一百余K,可以很方便的嵌入别的程序里。
  • 可扩展:Lua提供了非常易于使用的扩展接口和机制:由宿主语言(通常是C或C++)提供这些功能,Lua可以使用它们,就像是本来就内置的功能一样。

lua语法教程

redis使用Lua脚本

Redis 脚本使用 Lua 解释器来执行脚本。 Redis 2.6 版本通过内嵌支持 Lua 环境。执行脚本的常用命令为 EVAL。redis Eval 命令基本语法如下:

redis 127.0.0.1:6379> EVAL script numkeys key [key ...] arg [arg ...] 

参数说明:

  • script: 参数是一段 Lua 5.1 脚本程序。脚本不必(也不应该)定义为一个 Lua 函数。
  • numkeys: 用于指定键名参数的个数。
  • key [key ...]: 从 EVAL 的第三个参数开始算起,表示在脚本中所用到的那些 Redis 键(key),这些键名参数可以在 Lua 中通过全局变量 KEYS 数组,用 1 为基址的形式访问( KEYS[1] , KEYS[2] ,以此类推)。
  • arg [arg ...]: 附加参数,在 Lua 中通过全局变量 ARGV 数组访问,访问的形式和 KEYS 变量类似( ARGV[1] 、 ARGV[2] ,诸如此类)。

Jedis实现接口限流

首先,我们定义一个lua脚本:

local key = KEYS[1];

local times = ARGV[1];

local expire = ARGV[2];

local afterval = redis.call('incr',key);
if afterval ==1 then
    redis.call('expire',key,tonumber(expire) )
    return 1;
end;

if afterval > tonumber(times) then
    return 0;
end

return 1;

这个脚本首先定义了三个成员变量用来获取方法中传入的值,redis.call()方法是redis的命令脚本执行,即redis执行incr操作,对key中存储的key值加1操作,如果afterval值等于1时,执行redis的expire,设置key的过期时间,tonumber是将参数值转换为数值,返回,如果加一后的值大于我们传入的规定值时,返回0,进行限流。

java代码实现限流

    public boolean acquire(String limitKey, int limit, int expire) {
        Jedis jedis = new Jedis("127.0.0.1", 6379);
        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
        redisScript.setResultType(Long.class);
        redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("rateLimiter.lua")));
        Long result = (Long) jedis.eval(redisScript.getScriptAsString(), 1, limitKey, String.valueOf(limit), String.valueOf(expire));
        if (result == 0){
            return false;
        }else {
        return true;
        }
    }

controller层调用

     if (isAcquire.acquire("myKey",10,60)){
          // 接口放行
           return "success";
       }else {
         // 接口拒绝
           return "err";
       }

这个方法是传入一个你的key,这个key下每一分钟只能请求10次,如果超出10次,进行限流操作,等到上次请求接口的时间超出1分钟后才可以进行放行操作。

END

标签:脚本,return,Lua,redis,lua,限流,key
From: https://www.cnblogs.com/libinscloud/p/18145150

相关文章

  • redis 设置了 bind 后开机自启动报错
    redis设置了bind后开机自启动报错‍虚拟机中安装的redis​,在配置文件中设置了bind​,开机自启动时遇到:[root@localhost~]#tail-f/var/log/redis/redis.log849:C18Apr202407:18:49.475#oO0OoO0OoO0OoRedisisstartingoO0OoO0OoO0Oo849:C18Apr202407:18:......
  • centos 7 安装 redis 的脚本文件
    新建Bash脚本文件viminstall_redis.sh复制脚本文件点击查看代码#!/bin/bash#安装版本redis_version="6.2.7"#默认安装目录,可以通过第一个参数指定redis_installDir="/opt/redis"#Redis密码和端口,可以通过第二个和第三个参数指定#默认密码为"yourpassword",默......
  • redis自学(37)集群伸缩
    集群伸缩添加一个节点到集群:Redis-cli--cluster提供了很多操作集群的命令,可以通过下面方式查看:  比如,添加节点的命令  先输入新增的ip和端口号,后输入集群已经有的ip和端口号好指定添加到哪个集群。默认是增加master节点,加上--cluster-slave是变成了slave。--cluster......
  • redis的事务
    回顾阳哥的redis视频,总结一下redis的事务。是什么可以一次执行多个命令,本质就是一组命令的集合,一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其它命令插入,不允许加塞。能干嘛一个队列中,一次性,顺序性,排他性的执行一系列命令。watch监控watch使得exec命令需要有......
  • 【Docker】Docker部署Redis
    ✨Docker本文介绍DockerDesktop以及docker命令行的简单使用DockerDesktop安装使用请查阅官方文档GetDocker|DockerDocumentation在Windows上安装DockersDesktop可参考【Docker】DockerDesktopforWindows(WSL2)安装-双份浓缩馥芮白-博客园(cnblogs.com)似乎......
  • 多RedisTemplate配置
    SpringBoot自2.0版本开始默认使用Lettuce作为Redis的客户端,多RedisTemplate配置方法如下:先对lettuce连接池配置,基于lettuce配置多数据源的连接工厂,使用@Primary标注为首选的bean,以及指定并名称,再基于连接工厂配置多数据源的redisTemplate。点击查看代码packagecom.hnltd.a......
  • redis 哨兵部署
    redis生产哨兵的测试1、helmrelease的版本helmrepoaddbitnamihttps://charts.bitnami.com/bitnamihelmpullbitnami/redis--version18.2.2sentinel-redis]#lsredisredis-18.2.2.tgzvalues.yaml配置文件注意配置文件的cm部分,先使用默认的configmap配置然后再......
  • 腾讯音乐:说说Redis脑裂问题?
    Redis脑裂问题是指,在Redis哨兵模式或集群模式中,由于网络原因,导致主节点(Master)与哨兵(Sentinel)和从节点(Slave)的通讯中断,此时哨兵就会误以为主节点已宕机,就会在从节点中选举出一个新的主节点,此时Redis的集群中就出现了两个主节点的问题,就是Redis脑裂问题。脑裂问题影响Redis......
  • docker部署redis
    拉取镜像dockerpullredis:6.2.6创建映射目录和文件mkdir-p/data/server/docker_redis/data官网下载对应版本redis.conf,放在/data/server/docker_redis/目录下运行redisdockerrun-d-p6379:6379--name=redis--privileged=true-v/data/server/docker_redis/redis.c......
  • redis自学(36)散列插槽
    散列插槽Redis会把每一个master节点映射到0~16383共16284个插槽(hashslot)上,查看集群信息时就能看到:  数据key不是与节点绑定,而是与插槽绑定。Reids会根据key的有效部分计算插槽值,分两种情况:l Key中包含“{}”,且“{}”中至少包含1个字符,“{}”中的部分是有效部分l Key中......