对前端限流操作(Redis版本)4种算法

固定时间窗口算法

  • 固定时间窗口算法也可以叫做简单计数算法。网上有很多都将计数算法单独抽离出来。但是笔者认为计数算法是一种思想,而固定时间窗口算法是他的一种实现
  • 包括下面滑动时间窗口算法也是计数算法的一种实现。因为计数如果不和时间进行绑定的话那么失去了限流的本质了。就变成了拒绝了

在这里插入图片描述

优点

  • 在固定的时间内出现流量溢出可以立即做出限流。每个时间窗口不会相互影响
  • 在时间单元内保障系统的稳定。保障的时间单元内系统的吞吐量上限

缺点

  • 正如图示一样,他的最大问题就是临界状态。在临界状态最坏情况会受到两倍流量请求
  • 除了临界的情况,还有一种是在一个单元时间窗内前期如果很快的消耗完请求阈值。那么剩下的时间将会无法请求。这样就会因为一瞬间的流量导致一段时间内系统不可用。这在互联网高可用的系统中是不能接受的。

实现

	@Autowiredprivate StringRedisTemplate redisTemplate;// 固定时间窗口算法@GetMapping("/start")public Map<String, Object> start(@RequestParam Map<String, Object> paramMap) {//根据前端传递的qps上线int times = 100;if (paramMap.containsKey("times")) {times = Integer.parseInt(paramMap.get("times").toString());}String redisKey = "redisQps";RedisAtomicInteger redisAtomicInteger = new RedisAtomicInteger(redisKey, Objects.requireNonNull(redisTemplate.getConnectionFactory()));int no = redisAtomicInteger.getAndIncrement();//设置时间固定时间窗口长度 1Sif (no == 0) {redisAtomicInteger.expire(1, TimeUnit.SECONDS);}//判断是否超限  time=2 表示qps=3log.info("no值->{}",no);if (no > times) {throw new RuntimeException("qps refuse request");}log.info("times值->{}",times);//返回成功告知Map<String, Object> map = new HashMap<>();map.put("success", "success");return map;}

测试

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

滑动时间窗口算法

滑动时间窗口算法是一种限流算法,其原理是记录一段时间内的请求数量,并根据时间窗口的滑动来判断是否接受新的请求。该算法通过维护一个滑动窗口来记录时间窗口内的请求数量,并根据窗口的大小和限流阈值来决定是否接受新的请求。

滑动时间窗口算法的实现方式相对复杂一些,但相对于固定时间窗口算法更加灵活和精确。在滑动时间窗口算法中,时间窗口是不断滑动的,每个窗口的大小和起点可以根据实际需求进行配置。同时,该算法也支持动态调整限流阈值和流量控制粒度,能够更好地应对流量波动和突发请求的情况。

滑动时间窗口算法的核心思想是通过维护一个时间窗口内的请求计数器,并根据时间窗口的滑动来判断是否接受新的请求。具体来说,当一个新的请求到达时,算法会根据当前时间点判断该请求属于哪个时间窗口,并更新对应窗口的计数器。如果计数器已经达到了限流阈值,则拒绝该请求;否则,接受该请求。随着时间的推移,时间窗口会不断滑动,并更新计数器的值。

滑动时间窗口算法相对于固定时间窗口算法更加灵活和精确,能够更好地应对流量波动和突发请求的情况。同时,该算法也支持动态调整限流阈值和流量控制粒度,能够更好地满足实际需求。在实际应用中,需要根据具体情况选择适合的限流算法来控制流量。

优点

滑动时间窗口算法的优点主要包括以下几点:

  1. 灵活性和可配置性强:滑动时间窗口算法的时间窗口大小和起点可以根据实际需求进行配置,同时限流阈值也可以动态调整,这使得算法能够更好地应对流量波动和突发请求的情况。
  2. 精度高:滑动时间窗口算法相对于固定时间窗口算法更加精确,因为它考虑了时间窗口内的请求数量和时间点,能够更好地反映请求的实际情况。
  3. 支持多维度限流:滑动时间窗口算法可以支持多维度的限流,例如根据IP地址、用户ID、接口等不同维度进行限流,这使得算法能够更加精细地控制流量。

缺点

然而,滑动时间窗口算法也存在一些缺点:

  1. 实现复杂度高:滑动时间窗口算法的实现相对复杂,需要维护一个滑动窗口来记录时间窗口内的请求数量,并不断更新窗口的值,这需要耗费更多的计算和存储资源。
  2. 内存占用大:由于滑动时间窗口算法需要记录每个时间窗口内的请求数量和时间点,因此需要占用更多的内存资源。
  3. 无法平滑地实现请求流量的控制:滑动时间窗口算法只能通过控制时间段来控制请求总量,无法平滑地实现请求流量的控制,这可能会影响到用户体验和系统的稳定性。

实现

  • 滑动时间窗口是将时间更加细化,上面我们是通过redis#setnx实现的。这里我们就无法通过他统一记录了。我们应该加上更小的时间单元存储到一个集合汇总。然后根据集合的总量计算限流。redis的zsett数据结构就和符合我们的需求。
  • 为什么选择zset呢,因为redis的zset中除了值以外还有一个权重。会根据这个权重进行排序。如果我们将我们的时间单元及时间戳作为我们的权重,那么我们获取统计的时候只需要按照一个时间戳范围就可以了。
  • 因为zset内元素是唯一的,所以我们的值采用uuid或者雪花算法一类的id生成器
// 滑动时间窗口算法@GetMapping("/startList")public Map<String, Object> startList(@RequestParam Map<String, Object> paramMap) {String redisKey = "qpsZset";Integer times = 100;if (paramMap.containsKey("times")) {times = Integer.valueOf(paramMap.get("times").toString());}long currentTimeMillis = System.currentTimeMillis();long interMills = 10000L;Long count = redisTemplate.opsForZSet().count(redisKey, currentTimeMillis - interMills, currentTimeMillis);// 检查QPS(Queries Per Second)是否超过限制/*** 使用System.currentTimeMillis()获取当前时间戳。* 设置一个时间间隔interMills为1000毫秒(即1秒)。* 使用redisTemplate.opsForZSet().count(redisKey, currentTimeMillis - interMills, currentTimeMillis)查询过去1秒内Redis ZSet中指定键(redisKey)的数量。这个数量会被赋值给count变量。* 如果count的值大于times,则抛出一个运行时异常,表示QPS超过限制*/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;}

在这里插入图片描述

漏桶算法

漏桶算法是一种常用于流量控制和限流的算法,其核心思想是将突发流量整形以便为网络提供一个稳定的流量。

漏桶算法可以看作是一个带有常量服务时间的单服务器队列,如果漏桶(包缓存)溢出,那么数据包会被丢弃。在网络中,漏桶算法可以控制端口的流量输出速率,平滑网络上的突发流量,实现流量整形,从而为网络提供一个稳定的流量。

漏桶算法的实现相对简单,不需要复杂的数据结构或计算,易于理解和部署。其优点包括平滑处理流入系统的请求,以恒定的速率将请求处理释放,从而避免了突发请求对系统的冲击;控制精度高,可以通过调整漏桶的出水速率来精确地控制请求的处理速度;适用于需要平滑处理流量和避免突发请求的场景,例如网络流量控制、防止DDOS攻击等。

然而,漏桶算法也存在一些缺点,例如请求延迟,可能导致某些请求的响应时间变长;不适用于实时性要求高的场景,因为请求需要按照恒定速率进行处理,无法满足即时性要求;无法应对突发流量,因为漏桶的出水速率是固定的,无法根据流量的变化进行动态调整。

在这里插入图片描述

优点

  • 面对限流更加的柔性,不在粗暴的拒绝。
  • 增加了接口的接收性
  • 保证下流服务接收的稳定性。均匀下发

实现

    // 漏桶算法@GetMapping("/startLoutong")public Map<String, Object> startLoutong(@RequestParam 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");}// 添加请求到队列Redis列表的右侧。Long aLong = redisTemplate.opsForList().rightPush(redisKey, String.valueOf(paramMap));if (aLong > times) {//为了防止并发场景。这里添加完成之后也要验证。  即使这样本段代码在高并发也有问题。此处演示作用// 修剪Redis列表,使其长度为timesredisTemplate.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
@Slf4j
public class SchedulerTask {@Autowiredprivate StringRedisTemplate redisTemplate;@Scheduled(cron = "*/5 * * * * ?")private void process() {//一次性消费两个log.info("正在消费。。。。。。");String redisKey = "qpsList";redisTemplate.opsForList().trim(redisKey, 2, -1);}}

测试

在这里插入图片描述

令牌桶算法

  • 令牌桶和漏桶法是一样的。只不过将桶的作用方向改变了一下。
  • 漏桶的出水速度是恒定的,如果流量突然增加的话我们就只能拒绝入池
  • 但是令牌桶是将令牌放入桶中,我们知道正常情况下令牌就是一串字符当桶满了就拒绝令牌的入池,但是面对高流量的时候正常加上我们的超时时间就留下足够长的时间生产及消费令牌了。这样就尽可能的不会造成请求的拒绝
  • 最后,不论是对于令牌桶拿不到令牌被拒绝,还是漏桶的水满了溢出,都是为了保证大部分流量的正常使用,而牺牲掉了少部分流量

实现

    // 令牌桶算法@GetMapping("/startLingpaitong")public Map<String, Object> startLingpaitong(Map<String, Object> paramMap) {String redisKey = "lingpaitong";String token = redisTemplate.opsForList().leftPop(redisKey);//正常情况需要验证是否合法,防止篡改if (StringUtils.isEmpty(token)) {throw new RuntimeException("令牌桶拒绝");}Map<String, Object> map = new HashMap<>();map.put("success", "success");return map;}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/689682.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

文心一言API使用教程(python版)

注&#xff1a;在做项目的时候需要调用文心一言&#xff0c;发现网上的版本很乱&#xff0c;基本都止步在官方文档的代码上&#xff0c;所以写了一篇博客来记录自己的尝试实现了对文心一言的循环调用和自定义询问&#xff0c;本篇文章不需要有任何对api的基础知识&#xff0c;代…

PNG图片压缩-UPNG.js参数说明及示例

UPNG.js是一个非常轻量且高效的库&#xff0c;用于处理PNG图像。它可以编码和解码PNG图片&#xff0c;同时支持压缩和解压缩功能。特别适合在前端项目中处理图像&#xff0c;尤其是在需要优化图像大小而不牺牲质量时。 UPNG.encode()函数是UPNG.js中用于将图像数据编码成PNG格…

lv15 input子系统框架、外设驱动开发 5

一、input子系统基本框架 在我们日常的Linux系统中&#xff0c;存在大量的输入设备&#xff0c;例如按键、鼠标、键盘、触摸屏、摇杆等&#xff0c;他们本身就是字符设备&#xff0c;linux内核将这些字符设备的共同性抽象出来&#xff0c;简化驱动开发建立了一个input子系统。 …

羊大师的羊奶有几种口味呢?

羊大师提供的羊奶有6种不同口味可供选择。 1.新鲜羊奶不仅没有膻味&#xff0c;而且富含高钙无糖&#xff0c;并且含有丰富的优质蛋白质和超过200种营养物质。这非常适合缺钙或体弱的人饮用。 2.益生菌羊奶是一种含有保加利亚乳杆菌、嗜酸乳杆菌、双歧杆菌等益生菌群的产品&…

基于物联网的工业企业能耗监控系统

上海安科瑞电气股份有限公司 胡冠楠 咨询家&#xff1a;“Acrelhgn”&#xff0c;了解更多产品资讯 摘要&#xff1a;针对工业制造企业存在高能耗、高污染的问题&#xff0c;提出了一种用于工业企业能耗监控的多层级网络系统。本系统可完成企业内部电力、水资源以及燃气等能源…

如何探索和可视化用于图像中物体检测的 ML 数据

近年来&#xff0c;人们越来越认识到深入理解机器学习数据&#xff08;ML-data&#xff09;的必要性。不过&#xff0c;鉴于检测大型数据集往往需要耗费大量人力物力&#xff0c;它在计算机视觉&#xff08;computer vision&#xff09;领域的广泛应用&#xff0c;尚有待进一步…

陇剑杯 2021刷题记录

题目位置&#xff1a;https://www.nssctf.cn/上有 陇剑杯 2021 1. 签到题题目描述分析答案小结 2. jwt问1析1答案小结 问2析2答案小结 问3析3答案 问4析4答案 问5析5答案 问6析6答案 3. webshell问1析1答案 问2析2答案 问3析3答案 1. 签到题 题目描述 此时正在进行的可能是_…

防止被恶意调用API接口

前言 在面试时&#xff0c;经常会被问一个问题&#xff1a;如何防止别人恶意刷接口&#xff1f; 这是一个非常有意思的问题&#xff0c;防范措施挺多的。今天这篇文章专门跟大家一起聊聊&#xff0c;希望对你会有所帮助。 1 防火墙 防火墙是网络安全中最基本的安全设备之一&…

Linux RabbitMQ 安装及卸载

一、安装 1、前景 RabbitMQ是用Erlang编写的&#xff0c;所以需要先安装Erlang的编译环境 注意 Erlang和RabbitMQ的版本是有一些版本匹配关系的&#xff0c;如果不匹配会导致RabbitMQ无法启动 2、安装Erlang # 下载 wget https://packages.erlang-solutions.com/erlang/r…

家中R4S软路由iStoreOS配置内网穿透服务实现远程访问公司电脑桌面

文章目录 简介一、配置远程桌面公网地址二、家中使用永久固定地址 访问公司电脑**具体操作方法是&#xff1a;** 简介 软路由是PC的硬件加上路由系统来实现路由器的功能&#xff0c;也可以说是使用软件达成路由功能的路由器。 使用软路由控制局域网内计算机的好处&#xff1a…

【日常聊聊】深度学习进度

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;日常聊聊 ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 方向一&#xff1a;深度学习的基本原理和算法 方向二&#xff1a;深度学习的应用实例 方向三&#xff1a;深度学习的挑战和未…

JVM-JVM调优基础(理论)

申明&#xff1a;文章内容是本人学习极客时间课程所写&#xff0c;作为笔记进行记录&#xff0c;文字和图片基本来源于课程资料&#xff0c;在某些地方会插入一点自己的理解&#xff0c;未用于商业用途&#xff0c;侵删。 原资料地址&#xff1a;课程资料 JVM参数 标准参数 …

【正点原子STM32连载】 第五十章 手写识别实验 摘自【正点原子】APM32E103最小系统板使用指南

1&#xff09;实验平台&#xff1a;正点原子APM32E103最小系统板 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id609294757420 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/docs/boards/xiaoxitongban 第五…

lazada、速卖通卖家如何掌握自养号测评技巧打造高评价产品?

做跨境电商卖家都知道&#xff0c;国外的买家购物比较理性&#xff0c;也喜欢货比三家&#xff0c;所以店铺想要留住客户&#xff0c;就需要一些优质的产品来吸引他们。产品评价是卖家获取买家信任的重要途径&#xff0c;评价越高的产品&#xff0c;销量也就越好。 尤其是 Shop…

机器人常用传感器分类及一般性要求

机器人传感器的分类 传感技术是先进机器人的三大要素&#xff08;感知、决策和动作&#xff09;之一。根据用途不同&#xff0c;机器人传感器可以分为两大类&#xff1a;用于检测机器人自身状态的内部传感器和用于检测机器人相关环境参数的外部传感器。 内部传感器 内部传感…

CrossOver 24.0 让Mac可以运行Windows程序的工具

CrossOver 24.0最新版重点添加了对 DirectX 12 支持&#xff0c;从而在 Mac 上更好地模拟运行 Windows 游戏&#xff0c;开发者在 CrossOver 23 中可以调用 DirectX 12&#xff0c;在模拟游戏的过程中同时调用所有 GPU 核心&#xff0c;从而实现更优秀的渲染效果。 目前CrossOv…

CORROSION: 1

本机 192.168.223.128目标机 192.168.223.148 主机发现 nmap -sP 192.168.223.0/24 端口扫描 ​nmap -sV -p- -A 192.168.223.148开启了22 80 端口 看web&#xff0c;是个apache默认界面 扫目录 gobuster dir -u http://192.168.223.148 -x html,txt,php,bak --wordlist…

推送开权引导的技术内幕

人人都讨厌代码腐化&#xff0c;人人都在腐化代码&#xff01;本文介绍app消息推送开权提醒能力的服务端实现&#xff0c;并说明如何通过手搓一个简易的流程引擎来实现横向的业务场景隔离&#xff0c;纵向的业务流程编排&#xff0c;从而灵活支持业务需求&#xff0c;抑制代码腐…

曲线生成 | 图解B样条曲线生成原理(基本概念与节点生成算法)

目录 0 专栏介绍1 什么是B样条曲线&#xff1f;2 基函数的de Boor递推式3 B样条曲线基本概念图解4 节点生成公式 0 专栏介绍 &#x1f525;附C/Python/Matlab全套代码&#x1f525;课程设计、毕业设计、创新竞赛必备&#xff01;详细介绍全局规划(图搜索、采样法、智能算法等)…

java以及android类加载机制

类加载机制 一、Java类加载机制 java中&#xff0c;每一个类或者接口&#xff0c;在编译后&#xff0c;都会生成一个.class文件。 类加载机制指的是将这些.class文件中的二进制数据读入到内存中并对数据进行校验&#xff0c;解析和初始化。最终&#xff0c;每一个类都会在方…