Redis实现限流功能的优点:
  • 可以应用于分布式或者集群下
  • redis并发量大
Redis实现限流功能
Redis限流实现思路
使用redis中key的过期机制、key自增机制,
Redis实现限流功能

Redis实现限流功能
Redis实现限流功能
主类,可以在Filter或者HandlerInterceptor中定义,用于拦截请求
@GetMapping(value = "/limitRate")
    public ServiceResult limitRate() {
        ServiceResult serviceResult = null;
        if(redisManage.getValue("LimitCount")!=null) {
            Integer countExist = (Integer) redisManage.getValue("LimitCount");
            Long expireTimes = redisManage.getExpire("LimitCount");
            if(expireTimes>-1) {
                if(countExist>10) {
                    serviceResult = new ServiceResult(-102,"LimitCount没秒超过10次访问,返回错误");
                    serviceResult.setData(countExist);
                    return serviceResult;
                }else {
                    String count = String.valueOf(countExist+1);
                    redisManage.increValue("LimitCount");
                    serviceResult = new ServiceResult(HttpResultEnum.SUCCESS);
                    serviceResult.setData(count);
                    return serviceResult;
                }
            }else {
                redisManage.delValue("LimitCount");
                redisManage.putValueExpireTimes("LimitCount",1,10L);
                serviceResult = new ServiceResult(100,"LimitCount超时,删除后,创建LimitCount=1");
                serviceResult.setData(1);
                return serviceResult;
            }
        }else {
            redisManage.putValueExpireTimes("LimitCount",1,10L);
            serviceResult = new ServiceResult(100,"LimitCount不存在,创建LimitCount=1");
            serviceResult.setData(1);
            return serviceResult;
        }
    }

 

 
Redis实现类
     
    /**
     * 自增
     * @param key
     * @return
     */
    public Integer increValue(String key) {
        ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
        try{
            valueOperations.increment(key,1);
            LoggerUtil.info(logger, "key自增=" + valueOperations.get(key));
        }catch (Exception ex) {
            ex.printStackTrace();
        }
        return (Integer) valueOperations.get(key);
    }

    /**
     * 删除Redis中信息
     * @param key
     * @return
     */
    public void delValue(String key) {
        LoggerUtil.info(logger, "删除key=" + key);
        if (redisTemplate.hasKey(key)) {
            redisTemplate.delete(key);
        }
    }
    
    /**
     * 保存信息到Redis中,增加超时时间
     * @param key
     * @param value
     * @param expireTimes default 3600s
     */
    public void putValueExpireTimes(String key,String value,Long expireTimes) {
        LoggerUtil.info(logger, "保存key=" + key+";value=" + value);
        redisTemplate.opsForValue().set(key,value);
        if(expireTimes==null || expireTimes == 0L) {
            expireTimes = 3600L;
        }
        redisTemplate.expire(key, expireTimes, TimeUnit.SECONDS);
        LoggerUtil.info(logger, "设置超时时间:" + redisTemplate.getExpire(key, TimeUnit.SECONDS));
    }

 

 
Redis连接池:
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;

@Configuration
public class RedisConfig {

    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private int port;

    @Value("${spring.redis.timeout}")
    private int timeout;

    @Value("${spring.redis.password}")
    private String password;

    @Value("${spring.redis.database}")
    private int database;

    @Value("${spring.redis.pool.max-idle}")
    private int maxIdle;

    @Value("${spring.redis.pool.min-idle}")
    private int minIdle;

    @Value("${spring.redis.pool.max-active}")
    private int maxActive;

    /**
     * redis模板,存储关键字是字符串,值是Jdk序列化
     * @Description:
     * @param factory
     * @return
     */
    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
        StringRedisTemplate template = new StringRedisTemplate(factory);
        setSerializer(template); //设置序列化工具,这样ReportBean不需要实现Serializable接口
        template.afterPropertiesSet();
        return template;
    }

    private void setSerializer(StringRedisTemplate template) {
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        template.setValueSerializer(jackson2JsonRedisSerializer);
    }


    /**
     * redis连接的基础设置
     * @Description:
     * @return
     */
    @Bean
    public JedisConnectionFactory redisConnectionFactory() {
        JedisConnectionFactory factory = new JedisConnectionFactory();
        factory.setHostName(host);
        factory.setPort(port);
        factory.setPassword(password);
        //存储的库
        factory.setDatabase(database);
        //设置连接超时时间
        factory.setTimeout(timeout);
        factory.setUsePool(true);
        factory.setPoolConfig(jedisPoolConfig());
        return factory;
    }

    /**
     * 连接池配置
     * @Description:
     * @return
     */
    @Bean
    public JedisPoolConfig jedisPoolConfig() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxIdle(maxIdle);
        jedisPoolConfig.setMinIdle(minIdle);
        jedisPoolConfig.setMaxTotal(maxActive);
        return jedisPoolConfig;
    }

 

}