• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    redis实现的四种常见限流策略

    引言

    固定时间窗口算法

    优点

    缺点

    实现

    controller

    @RequestMapping(value = "/start",method = RequestMethod.GET)
        public Mapstring,object> start(@RequestParam Mapstring, object=""> paramMap) {
            return testService.startQps(paramMap);
        }

    service

    @Override
    public Mapstring, object=""> startQps(Mapstring, object=""> paramMap) {
        //根据前端传递的qps上线
        Integer times = 100;
        if (paramMap.containsKey("times")) {
            times = Integer.valueOf(paramMap.get("times").toString());
        }
        String redisKey = "redisQps";
        RedisAtomicInteger redisAtomicInteger = new RedisAtomicInteger(redisKey, redisTemplate.getConnectionFactory());
        int no = redisAtomicInteger.getAndIncrement();
        //设置时间固定时间窗口长度 1S
        if (no == 0) {
            redisAtomicInteger.expire(1, TimeUnit.SECONDS);
        }
        //判断是否超限  time=2 表示qps=3
        if (no > times) {
            throw new RuntimeException("qps refuse request");
        }
        //返回成功告知
        Mapstring, object=""> map = new HashMap>();
        map.put("success", "success");
        return map;
    }

    结果测试

    我们设置的qps=3 , 我们可以看到五个并发进来后前三个正常访问,后面两个就失败了。稍等一段时间我们在并发访问,前三个又可以正常访问。说明到了下一个时间窗口

    滑动时间窗口算法

    优点

    缺点

    实现

    controller

    @RequestMapping(value = "/startList",method = RequestMethod.GET)
        public Mapstring,object> startList(@RequestParam Mapstring, object=""> paramMap) {
            return testService.startList(paramMap);
        }

    service

    @RequestMapping(value = "/startList",method = RequestMethod.GET)
        public Mapstring,object> startList(@RequestParam Mapstring, object=""> paramMap) {
            return testService.startList(paramMap);
        }

    结果测试

    漏桶算法

    优点

    缺点

    实现

    controller

    @RequestMapping(value = "/startLoutong",method = RequestMethod.GET)
    public Mapstring,object> startLoutong(@RequestParam Mapstring, object=""> paramMap) {
        return testService.startLoutong(paramMap);
    }

    service

    在service中我们通过redis的list的功能模拟出桶的效果。这里代码是实验室性质的。在真实使用中我们还需要考虑并发的问题

    @Override
    public Mapstring, object=""> startLoutong(Mapstring, object=""> paramMap) {
        String redisKey = "qpsList";
        Integer times = 100;
        if (paramMap.containsKey("times")) {
            times = Integer.valueOf(paramMap.get("times").toString());
        }
        Long size = redisTemplate.opsForList().size(redisKey);
        if (size >= times) {
            throw new RuntimeException("qps refuse request");
        }
        Long aLong = redisTemplate.opsForList().rightPush(redisKey, paramMap);
        if (aLong > times) {
            //为了防止并发场景。这里添加完成之后也要验证。  即使这样本段代码在高并发也有问题。此处演示作用
            redisTemplate.opsForList().trim(redisKey, 0, times-1);
            throw new RuntimeException("qps refuse request");
        }
        Mapstring, object=""> map = new HashMap>();
        map.put("success", "success");
        return map;
    }

    下游消费

    @Component
    public class SchedulerTask {
    
        @Autowired
        RedisTemplate redisTemplate;
    
        private String redisKey="qpsList";
    
        @Scheduled(cron="*/1 * * * * ?")
        private void process(){
            //一次性消费两个
            System.out.println("正在消费。。。。。。");
            redisTemplate.opsForList().trim(redisKey, 2, -1);
        }
    
    }

    测试

    令牌桶算法

    令牌桶和漏桶法是一样的。只不过将桶的作用方向改变了一下。

    漏桶的出水速度是恒定的,如果流量突然增加的话我们就只能拒绝入池

    但是令牌桶是将令牌放入桶中,我们知道正常情况下令牌就是一串字符当桶满了就拒绝令牌的入池,但是面对高流量的时候正常加上我们的超时时间就留下足够长的时间生产及消费令牌了。这样就尽可能的不会造成请求的拒绝

    最后,不论是对于令牌桶拿不到令牌被拒绝,还是漏桶的水满了溢出,都是为了保证大部分流量的正常使用,而牺牲掉了少部分流量

    public Mapstring, object=""> startLingpaitong(Mapstring, object=""> paramMap) {
            String redisKey = "lingpaitong";
            String token = redisTemplate.opsForList().leftPop(redisKey).toString();
            //正常情况需要验证是否合法,防止篡改
            if (StringUtils.isEmpty(token)) {
                throw new RuntimeException("令牌桶拒绝");
            }
            Mapstring, object=""> map = new HashMap>();
            map.put("success", "success");
            return map;
        }
    @Scheduled(cron="*/1 * * * * ?")
        private void process(){
            //一次性生产两个
            System.out.println("正在消费。。。。。。");
            for (int i = 0; i  2; i++) {
                redisTemplate.opsForList().rightPush(redisKey, i);
            }
        }

    到此这篇关于基于redis实现的四种常见的限流策略的文章就介绍到这了,更多相关redis 限流策略内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    您可能感兴趣的文章:
    • springboot+redis 实现分布式限流令牌桶的示例代码
    • 详解Redis实现限流的三种方式
    • Python+redis通过限流保护高并发系统
    • Springboot使用redis进行api防刷限流过程详解
    • Redis和Lua实现分布式限流器的方法详解
    • php使用lua+redis实现限流,计数器模式,令牌桶模式
    • 基于Redis的限流器的实现(示例讲解)
    • 基于Redis实现分布式应用限流的方法
    • 详解基于redis实现的四种常见的限流策略
    上一篇:Redis 哨兵集群的实现
    下一篇:Redis基于Bitmap实现用户签到功能
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    redis实现的四种常见限流策略 redis,实现,的,四种,常见,