zoukankan      html  css  js  c++  java
  • Redis实现限流功能

    Redis实现限流功能的优点:
    • 可以应用于分布式或者集群下
    • redis并发量大
    Redis限流实现思路
    使用redis中key的过期机制、key自增机制,
    主类,可以在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;
        }
    }
    收藏文章数量从多到少与“把书读薄”是一个道理
  • 相关阅读:
    utf8和utf8mb4的区别
    【JSP 标签】选择判断c:choose
    【JSP 标签】格式化日期
    【Spring 核心】AOP 面向切面编程
    【Spring 核心】高级装配
    【Spring 核心】装配bean(三)XML配置
    【Spring 核心】装配bean(二) JavaConfig装配
    【Spring 核心】装配Bean(一) 自动化装配
    【Js应用实例】图片预览
    【Js应用实例】限制上传图片大小
  • 原文地址:https://www.cnblogs.com/use-D/p/9544903.html
Copyright © 2011-2022 走看看