springboot中使用redis限流

springboot中使用redis限流

pom.xml

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.6.6</version>
</parent>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
</dependencies>

application.yml

spring:
  redis:
    host: 127.0.0.1
    port: 6379
    lettuce:
      pool:
        max-active: 8
        max-idle: 8
        min-idle: 0

redis.config

@Configuration
public class RedisConfig {

    @Bean
    public StringRedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(connectionFactory);
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }

    /**
     * 初始化将lua脚本加载到redis脚本中
     * @return 脚本实例
     */
    @Bean("limitRedisScript")
    public DefaultRedisScript<Boolean> loadRedisScript() {
        DefaultRedisScript<Boolean> redisScript = new DefaultRedisScript<>();
        redisScript.setLocation(new ClassPathResource("redisScript/limit.lua"));
        redisScript.setResultType(Boolean.class);
        return redisScript;
    }
}

resource目录下创建redisScript文件夹
springboot中使用redis限流_第1张图片
limit.lua

local key = KEYS[1] --限流KEY

local limit = tonumber(ARGV[1]) --限流大小

local expireTime = tonumber(ARGV[2]) --过期时间 单位/s

local exists = redis.call("EXISTS", key) --key是否已存在

if exists == 0 then --如果key不存在
    redis.call("INCRBY", key, 1) --请求数+1
    redis.call("EXPIRE", key, expireTime) --设置1秒过期
else
    local current = tonumber(redis.call("get", key) or "0")
    if current + 1 > limit then
        return false
    else
        redis.call("INCRBY", key, 1) --请求数+1
    end
end
return true

RedisUtil

@Component
public class RedisUtil {

	@Resource
    private StringRedisTemplate redisTemplate;

	@Resource
    private RedisScript<Boolean> redisScript;

    /**
     * 执行lua脚本
     * @param keyList rediskey集合
     * @param limit 限流大小
     * @param expireTime 过期时间 单位/s
     * @return
     */
    public boolean execute(List<String> keyList, int limit, Long expireTime) {
        return redisTemplate.execute(redisScript, keyList, limit, expireTime);
    }
}

你可能感兴趣的:(限流,redis,数据库,lua)