springboot编写redis的lua脚本

配置redis

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String,String> redisTemplate(RedisConnectionFactory factory){
        return new StringRedisTemplate(factory);
    }

    @Bean
    public DefaultRedisScript loadRedisScript(){
        DefaultRedisScript redisScript=new DefaultRedisScript();
        //设置lua脚本
        redisScript.setLocation(new ClassPathResource("redisLimit.lua"));
        //设置返回类型
        redisScript.setResultType(java.lang.Boolean.class);
        return redisScript;
    }
}

编写redisLimit.lua脚本并放到项目的resource目录下

-- 查询key值如果大于0,则减一
-- tonumber 把字符串转成数值
if tonumber(redis.call('GET', KEYS[1])) > 0 then
    redis.call('DECR', KEYS[1])
    return true
else
    return false
end
@RestController
@RequestMapping("/test")
public class UserController {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private DefaultRedisScript<Boolean> loadRedisScript;


    @RequestMapping("/test")
    public void test() {
        Boolean flag = redisTemplate.execute(loadRedisScript, Arrays.asList("number"));
        System.out.println(flag);
    }
}

限流脚本1:

-- 在lua脚本中,有两个全局的变量,是用来接收redis应用端传递的键值和其它参数的,
-- 分别为KEYS、ARGV。

-- 在应用端传递给KEYS时是一个数组列表,在lua脚本中通过索引方式获取数组内的值。

-- 在应用端,传递给ARGV的参数比较灵活,可以是多个独立的参数,但对应到Lua脚本中是,
-- 统一用ARGV这个数组接收,获取方式也是通过数组下标获取。
-- tonumber 把字符串转成数值
local key = KEYS[1]
local max = tonumber(ARGV[1])

-- 如果key不存在设置key并设置过期时间
if tonumber(redis.call('EXISTS', key)) == 0 then
    redis.call('SETNX', key, 0)
    redis.call('EXPIRE', key, 60)
end
local  count = tonumber(redis.call('GET', key))
if count + 1 <= max then
    -- 没有超过阈值,设置当前访问的数量+1
    redis.call('INCR', key)
    return true
else
    return false
end

限流脚本2:

local key = KEYS[1]
local nowTime = tonumber(ARGV[1])
local unitExpiredTime = tonumber(ARGV[2])
local max = tonumber(ARGV[3])


local expiredTime = nowTime - unitExpiredTime
-- 移除过期时间之前的数据
redis.call('ZREMRANGEBYSCORE', key, 0, expiredTime)
-- 获取集合元素数量
local count = tonumber(redis.call('ZCARD', key))

if count + 1 > max then
    return false
else
    -- 注意每个请求的value值不能一重复
    -- 添加参数并设置过期时间
    redis.call('ZADD', key, nowTime, nowTime)
    redis.call('PEXPIRE', key, unitExpiredTime)
    return true
end



你可能感兴趣的:(缓存中间件,spring,boot,java,spring)