首页 > 数据库 > Redis实现限流的三种方式

Redis实现限流的三种方式

时间:2023-06-07 10:44:47浏览次数:60  
标签:令牌 窗口 Redis 限流 三种 return public redisTemplate

一、固定窗口

所谓固定窗口限流即时间窗口的起始和结束时间是固定的,在固定时间段内允许要求的请求数量访问,超过则拒绝;当固定时间段结束后,再重新开始下一个时间段进行计数。

我们可以根据当前的时间,以分钟为时间段,每分钟都生成一个key,用来inc,当达到请求数量就返回一些友好信息。

固定窗口

  1.   /**
  2.   * @author: AngJie
  3.   * @create: 2022-07-26 14:41
  4.   **/
  5.   @RestController
  6.   @RequestMapping("/redisTest")
  7.   public class RedisTestController {
  8.    
  9.   @Autowired
  10.   private RedisTemplate redisTemplate;
  11.    
  12.   private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm");
  13.    
  14.   @GetMapping("/Fixed")
  15.   public String testFixedWindow() {
  16.   String now = formatter.format(LocalDateTime.now());
  17.    
  18.   Long count = redisTemplate.opsForValue().increment(now + ":fixed");
  19.   if (count > 5) {
  20.   return "不好意思,服务器正忙,请一分钟后再试......";
  21.   } else {
  22.   return "服务端正在处理";
  23.   }
  24.   }
  25.   }

 

该方式优点是比较简单粗暴,缺点是不够灵活,对于边界问题不能够处理,如设置的时间段刚开始时流量占满了设置的最大次数,后面一段时间则不能够再进行访问,必须等该时间段过了后才可以再次访问。

二、滑动窗口

针对固定窗口限流的问题,可以采用滑动窗口来优化改善。所谓滑动窗口即设置的时间窗口的起始和结束时间是不断变化的,时间差值不变,允许的请求数量不变。

我们可以将请求打造成一个zset数组,当每一次请求进来的时候,value保持唯一,可以用UUID生成,而score可以用当前时间戳表示,因为score我们可以用来计算当前时间戳之内有多少的请求数量。而zset数据结构也提供了zrange方法让我们可以很轻易的获取到2个时间戳内有多少请求。

  1.   /**
  2.   * @author: AngJie
  3.   * @create: 2022-07-26 14:41
  4.   **/
  5.   @RestController
  6.   @RequestMapping("/redisTest")
  7.   public class RedisTestController {
  8.    
  9.   @Autowired
  10.   private RedisTemplate redisTemplate;
  11.    
  12.   @GetMapping("/Sliding")
  13.   public String testSlidingWindow() {
  14.   Long currentTime = System.currentTimeMillis();
  15.    
  16.   System.out.println(currentTime);
  17.   if (redisTemplate.hasKey("limit")) {
  18.   // intervalTime是限流的时间
  19.   Long intervalTime = 60000L;
  20.   Integer count = redisTemplate.opsForZSet().rangeByScore("limit", currentTime - intervalTime, currentTime).size();
  21.   System.out.println(count);
  22.   if (count != null && count > 5) {
  23.   return "每分钟最多只能访问5次";
  24.   }
  25.   }
  26.   redisTemplate.opsForZSet().add("limit", UUID.randomUUID().toString(), currentTime);
  27.   return "访问成功";
  28.   }
  29.   }

 

通过上述代码可以做到滑动窗口的效果,并且能保证每N秒内至多M个请求,缺点就是zset的数据结构会越来越大。实现方式相对也是比较简单的。

三、令牌桶

Redisson可以实现很多东西,在Redis的基础上,Redisson做了超多的封装,不仅可以用来实现分布式锁,还可以帮助我们实现令牌桶限流。

RateLimter主要作用就是可以限制调用接口的次数。主要原理就是调用接口之前,需要拥有指定个令牌。限流器每秒会产生X个令牌放入令牌桶,调用接口需要去令牌桶里面拿令牌。如果令牌被其它请求拿完了,那么自然而然,当前请求就调用不到指定的接口。

RateLimter实现限流

  1.   /**
  2.   * @author: AngJie
  3.   * @create: 2022-07-26 14:41
  4.   **/
  5.   @RestController
  6.   @RequestMapping("/redisTest")
  7.   public class RedisTestController {
  8.    
  9.   @Autowired
  10.   private RedisTemplate redisTemplate;
  11.    
  12.   @Autowired
  13.   private Redisson redisson;
  14.    
  15.   @GetMapping("/Token")
  16.   public String testTokenBucket() {
  17.   RRateLimiter rateLimiter = redisson.getRateLimiter("myRateLimiter");
  18.    
  19.   // 最大流速 = 每10秒钟产生1个令牌
  20.   rateLimiter.trySetRate(RateType.OVERALL, 1, 10, RateIntervalUnit.SECONDS);
  21.   //需要1个令牌
  22.   if (rateLimiter.tryAcquire(1)) {
  23.   return "令牌桶里面有可使用的令牌";
  24.   }
  25.   return "不好意思,请过十秒钟再来~~~~~~~";
  26.    
  27.   }
  28.   }

 

 

标签:令牌,窗口,Redis,限流,三种,return,public,redisTemplate
From: https://www.cnblogs.com/tiancai/p/17462676.html

相关文章

  • Redis哨兵模式搭建
    ##一:哨兵主要作用监控:监控redis主库及从库运行状态;通知:如果redis发生故障转移,可以通过邮件通知管理员;自动故障转移:一旦发现主库宕机,则在从库中通过选举新的master进行故障转移。##二:工作原理哨兵(sentinel)是一个分布式系统,你可以在一个架构中运行多个哨兵(sentinel)进程,......
  • 【Redis】【持久化】RDB 快照是怎么实现的?
    1  前言这节我们来看看持久化方式中的RDB哈。2  RDB快照虽说Redis是内存数据库,但是它为数据的持久化提供了两个技术。分别是「AOF日志和RDB快照」。这两种技术都会各用一个日志文件来记录信息,但是记录的内容是不同的。AOF文件的内容是操作命令;RDB文件的内容......
  • 【Redis】【持久化】AOF 持久化是怎么实现的?
    1  前言这节我们来看看持久化方式中的AOF哈。2  AOF日志试想一下,如果Redis每执行一条写操作命令,就把该命令以追加的方式写入到一个文件里,然后重启Redis的时候,先去读取这个文件里的命令,并且执行它,这不就相当于恢复了缓存数据了吗?这种保存写操作命令到日志的持久化方......
  • k8s实战案例之部署redis单机和redis cluster
    1、在k8s上部署redis单机1.1、redis简介redis是一款基于BSD协议,开源的非关系型数据库(nosql数据库),作者是意大利开发者SalvatoreSanfilippo在2009年发布,使用C语言编写;redis是基于内存存储,而且是目前比较流行的键值数据库(key-valuedatabase),它提供将内存通过网络远程共享的一种服......
  • 二、tienchin健身系统技术点复现-注解限流
    二、tienchin健身系统技术点复现-注解限流在上一章节写到编写lua脚本。基本的配置类都已经创建,下面创建一个请求获取IP的工具类和全局异常处理即可。1、创建工具类IpUtilspackagecom.yangjiapo.rate_limiter.utils;importjavax.servlet.http.HttpServletRequest;import......
  • 一、tienchin健身系统技术点复现-注解限流
    一、tienchin健身系统技术点复现-注解限流这个技术用到的点是用Java代码执行redis的lua脚本,采用请求接口方法注解@RateLimiter,前置通知拦截判断请求次数,做出限流操作。Gitee代码仓库-rate-limiter1、application.yml配置redis参数在application.yml中配置redis基......
  • 第六节 2定义函数的三种形式
    一、无参函数无参函数指的是没有任何参数传入的函数,它可以不需要任何输入。在Python中,定义无参函数非常简单,只需要在函数名后面加上一对空括号就可以了,例如:defsay_hello():print("Hello,World!")以上代码定义了一个名为say_hello的函数,它没有任何参数,函数体内部只有一......
  • 使用snap安装Redis并配置外网访问和访问密码
    使用snap安装Redis并配置外网访问和访问密码Redis是一个流行的开源内存数据库,用于处理数据存储和缓存。在本文中,我们将介绍如何使用snap安装Redis,并通过Redis的CLI(命令行界面)来配置外网访问和访问密码。snap是一种用于在Linux系统上安装软件的包管理器,它提供了简单且可靠的软件......
  • python redis 链接集群 阿里云集群
    前言集群redis不支持选dbcluster方法里没有支持选中db的选项,javapy都不行#pipinstallredis==3.5.3#pipinstallredis-py-cluster==2.1.3#亲测,我是使用的这两个版本进行处理的fromredisclusterimportRedisClusternodes=[{"host":"dsfwwqfggy65aadfggi.redis.r......
  • redis 集群安装
    redis-5版本的集群安装 1.5版本往上就不再使用ruby去创建集群了。 2.具体的创建步骤可以参见下面的博文。https://www.jianshu.com/p/e9eab2f4a564 3.redis集群开机自启:https://www.cnblogs.com/powerwu/articles/11606925.html 4.启动命令 1.redis-server/usr/local/red......