基于redis如何实现限流策略

发布时间:2021-06-21 11:02:27 作者:小新
来源:亿速云 阅读:172

这篇文章将为大家详细讲解有关基于redis如何实现限流策略,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

一、引言

二、固定时间窗口算法

基于redis如何实现限流策略

优点:

缺点:

实现:

controller

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

service

@Override
public Map<string, object=""> startQps(Map<string, 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");
    }
    //返回成功告知
    Map<string, object=""> map = new HashMap<>();
    map.put("success", "success");
    return map;
}

结果测试:

基于redis如何实现限流策略

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

基于redis如何实现限流策略

基于redis如何实现限流策略

三、滑动时间窗口算法

基于redis如何实现限流策略

优点:

缺点:

实现:

controller

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

service

String redisKey = "qpsZset";
Integer times = 100;
if (paramMap.containsKey("times")) {
    times = Integer.valueOf(paramMap.get("times").toString());
}
long currentTimeMillis = System.currentTimeMillis();
long interMills = inter * 1000L;
Long count = redisTemplate.opsForZSet().count(redisKey, currentTimeMillis - interMills, currentTimeMillis);
if (count > times) {
    throw new RuntimeException("qps refuse request");
}
redisTemplate.opsForZSet().add(redisKey, UUID.randomUUID().toString(), currentTimeMillis);
Map<string, object=""> map = new HashMap<>();
map.put("success", "success");
return map;

结果测试:

基于redis如何实现限流策略

四、漏桶算法

基于redis如何实现限流策略

优点:

缺点:

实现:

controller

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

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

@Override
public Map<string, object=""> startLoutong(Map<string, 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");
    }
    Map<string, 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);
    }

}

测试:

基于redis如何实现限流策略

五、令牌桶算法

public Map<string, object=""> startLingpaitong(Map<string, object=""> paramMap) {
    String redisKey = "lingpaitong";
    String token = redisTemplate.opsForList().leftPop(redisKey).toString();
    //正常情况需要验证是否合法,防止篡改
    if (StringUtils.isEmpty(token)) {
        throw new RuntimeException("令牌桶拒绝");
    }
    Map<string, 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如何实现限流策略”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

推荐阅读:
  1. redis实现限流的方式有几种
  2. 如何实现redis限流

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

redis

上一篇:php计算剩余几天的实现方法

下一篇:JVM对象创建与内存分配机制的原理是什么

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》