Redis客户端允许通过eval指令直接将lua脚本发送到服务器端执行,服务器会阻塞其它指令的执行,确保脚本的原子性;
一个对springboot redis框架进行重写,支持lettuce、jedis、连接池、同时连接多个集群、多个redis数据库、开发自定义属性配置的开源SDK
<dependency>
<groupId>io.github.mingyang66groupId>
<artifactId>emily-spring-boot-redisartifactId>
<version>4.3.9version>
dependency>
GitHub地址:https://github.com/mingyang66/spring-parent
EVAL script numkeys key [key ...] arg [arg ...]
eval指令的作用是将脚本发送给Redis服务器,然后由服务器执行脚本。脚本可以访问和操作Redis中的数据,并返回执行结果。
SET key value EX seconds: 指令设置键值对及过期时间
SET key value [EX seconds] [PX milliseconds] [NX|XX]:
key
:要设置的键名。value
:要设置的值。EX seconds
:可选参数,指定键的过期时间,以秒为单位。PX milliseconds
:可选参数,指定键的过期时间,以毫秒为单位。NX
:可选参数,只在键不存在时设置键的值。XX
:可选参数,只在键已存在时设置键的值。如果键已存在,SET指令会覆盖原有的值。
可以使用EX参数或PX参数来设置键的过期时间,如果同时设置了两个参数,以EX参数为准。
可以使用NX参数或XX参数来控制只在键不存在或键已存在时才设置值的行为。默认情况下,不使用这两个参数时,SET指令会始终设置值。
INCRBY key increment: 指令对指定键增加指定值
INCR key:执行自增操作,将key的值加1。
EXPIRE key seconds:设置key的过期时间,单位为秒。
限流lua脚本:
-- 要限流的键名
local key = KEYS[1]
-- 限流阀值
local limit = tonumber(ARGV[1])
-- 限流的时间窗口
local interval = tonumber(ARGV[2])
-- 当前访问数量
local current = tonumber(redis.call('GET', key) or "0")
-- 0:超过阀值 1:访问有效
if current + 1 > limit then
return 0
elseif current == 0 then
redis.call('SET', key, 1)
redis.call('EXPIRE', key, interval)
return 1;
else
redis.call('INCR', key)
return 1
end
基于spring data redis的客户端代码:
/**
* 基于lua脚本的限流工具
*
* @param redisTemplate redis模板工具类
* @param key 限流键名
* @param limit 限流阀值
* @param interval 限流的时间窗口
* @return true-访问有效,false-超过阀值
*/
public static boolean limit(RedisTemplate redisTemplate, String key, int limit, int interval) {
RedisScript<Long> script = RedisScript.of(new ClassPathResource("META-INF/scripts/limit.lua"), Long.class);
// 0:超过阀值 1:访问有效
Long count = (Long) redisTemplate.execute(script, Arrays.asList(key), limit, interval);
return count == 1 ? true : false;
}
public enum ReturnType {
/**
* Returned as Boolean
*/
BOOLEAN,
/**
* Returned as {@link Long}
*/
INTEGER,
/**
* Returned as {@link List