常用的限流算法有哪些?你听说过几种?

限流,就是指限制流量请求的频次。
在高并发情况下,它是一种保护系统的策略,避免了在流量高峰时系统崩溃,造成系统的不可用。

常见的限流算法有:

  • 计数器限流算法
  • 滑动窗口限流算法
  • 漏桶限流算法
  • 令牌桶限流算法

1. 计数器限流算法

计数器限流算法,是一种简单且直观的限流方法。它通过维护一个计数器变量来限制在特定时间间隔内的请求数量。这种算法的实现原理是在一段时间间隔内(如1分钟)对请求进行计数,并将计数结果与设置的最大请求数进行比较。如果请求数超过了最大值,则进行限流处理。当达到时间间隔的终点时,计数器会被清零,重新开始计数。计数器算法也被称为固定窗口算法。

比如限流100次/分钟可以这样实现:给定一个变量counter来记录处理的请求数量,当1分钟之内处理一个请求之后counter+1,1分钟之内的如果counter=100的话,后续的请求就会被全部拒绝。等到 1分钟结束后,将counter回归成0,重新开始计数。

计数器限流算法的实现可以非常简单,只需要一个计数器变量即可,每来一个请求就进行计数操作,无需复杂的逻辑设计。它直观易懂,设置明确的阈值,比如规定每秒允许的请求数,易于理解和配置。

计数器算法也有其局限性——窗口切换时的突增问题,在固定窗口算法中,当达到时间窗口切换点时,如果请求数突然增加,可能会导致短时间内大量请求通过限流检查,这被称为“突增问题”。

计数器算法还可以通过使用原子变量和循环数组等数据结构来优化实现,以支持分布式环境下的限流需求。

2. 滑动窗口限流算法

滑动窗口限流算法,本质上也是一种计数器。
它通过对时间窗口的滑动来管理请求的计数,从而实现对请求速率的限制。
与固定窗口算法相比,滑动窗口算法将时间窗口分为多个小周期,每个小周期都有自己的计数器。随着时间的滑动,过期的小周期数据被删除,这样可以更精确地控制流量。

比如,我们的接口限流每分钟处理60个请求,我们可以把 1 分钟分为60个窗口。每隔1秒移动一次,每个窗口一秒只能处理 不大于 60(请求数)/60(窗口数) 的请求, 如果当前窗口的请求计数总和超过了限制的数量的话就不再处理其他请求。

滑动窗口限流算法的实现原理可以概括为:

  • 定义时间窗口:首先,需要定义一个时间窗口的大小,例如1分钟。
  • 记录请求:每次有请求时,使用某种数据结构(如Redis中的zset)将这条请求记录下来。
  • 滑动窗口操作:随着时间轴向右移动,滑动窗口的思想是只保留当前时间窗口内的请求记录,而丢弃当前窗口之外的记录。当下次有请求进来时,我们只需要判断当前窗口内的请求是否超过阈值即可。
  • 限流策略:如果当前窗口内的请求数量超过了设定的阈值,则进行限流,不允许继续进行请求。否则,允许请求通过。

滑动窗口限流算法的优势在于其能够更精确地控制流量,尤其是在处理短时间内突发的高请求量时。通过动态调整时间窗口的起始点和结束点,可以有效地平滑流量波动,避免系统因瞬间高负载而崩溃。此外,滑动窗口限流算法还适用于需要精细控制访问频率的场景,如API接口访问限制、防止恶意攻击等。

在实际应用中,滑动窗口限流算法可以通过Redis等缓存系统实现,利用其提供的数据结构(如有序集合zset)来高效地管理请求记录和执行滑动窗口操作。这种实现方式不仅性能高效,还能够利用Redis的持久化和分布式特性,提高系统的可用性和可扩展性。

Spring Cloud 中的熔断框架 Hystrix,以及 Spring Cloud Alibaba中的Sentinel 都采用滑动窗口来做数据统计。

3. 漏桶限流算法

漏桶算法通过一个带有恒定流出速度的漏桶来模拟数据流量的处理过程。无论数据流入的速度如何变化,漏桶的流出速度始终保持不变。
基于MQ实现的 生产者-消费者 模型,就是一种漏桶限流算法。

在这里插入图片描述
漏桶限流算法的工作机制:

  • 数据流入:当数据包到达时,它们被放入漏桶中。如果漏桶未满,数据包将被接受并排队等待处理;如果漏桶已满,则根据算法策略处理(如丢弃数据包)。
  • 数据流出:漏桶中的数据以恒定的速率(r字节/秒)流出,注入网络。这个过程模拟了网络流量的平滑处理。
  • 限流策略:
    当请求速度大于漏桶的流出速度时,即请求量大于当前服务所能处理的最大极限值时,触发限流策略。此时,如果漏桶已满,新到达的数据包将被丢弃。
    当请求速度小于或等于漏桶的漏出速度时,即服务的处理能力大于或等于请求量时,正常执行。

漏桶算法能够提供一个稳定的流量输出,有效避免突发流量对系统的冲击。所有请求都按照相同的速率被处理,保证了公平性。
漏桶算法的漏出速率是固定的,无法应对需要突发传输的场景。在网络未发生拥塞时,漏桶算法可能无法充分利用网络资源。

并未考虑并发控制等复杂因素下的漏桶算法的基本原理代码:

class LeakyBucketRateLimiter {  private int capacity; // 漏桶容量  private int waterLevel; // 当前水位  private long lastLeakTime; // 上次漏水时间  private final long leakRate; // 漏水速率(每秒漏水量)  public LeakyBucketRateLimiter(int capacity, long leakRate) {  this.capacity = capacity;  this.leakRate = leakRate;  this.waterLevel = 0;  this.lastLeakTime = System.currentTimeMillis();  }  // 尝试获取访问权限  public synchronized boolean tryAcquire() {  // 模拟漏水过程  leak();  // 检查水位是否已满  if (waterLevel >= capacity) {  return false; // 拒绝访问  }  // 允许访问,水位加一  waterLevel++;  return true;  }  // 漏水方法  private void leak() {  long currentTime = System.currentTimeMillis();  long elapsedTime = currentTime - lastLeakTime;  int leakAmount = (int) (elapsedTime * (leakRate / 1000.0)); // 计算漏水量  if (leakAmount > 0) {  waterLevel = Math.max(0, waterLevel - leakAmount); // 更新水位  lastLeakTime = currentTime; // 更新上次漏水时间  }  }  
}

4. 令牌桶限流算法

令牌桶算法使用一个固定容量的桶来存放令牌,这些令牌以恒定的速率被添加到桶中。当数据包需要发送到网络时,它们会消耗桶中的令牌。如果桶中有足够的令牌,数据包将被允许发送;否则,数据包可能需要等待或被丢弃。
相对于漏桶限流算法来说,令牌桶限流算法可以处理突发流量的问题。

只要桶中有足够的令牌,就可以以峰值速率发送流量。
通过调整令牌桶的容量和令牌生成速率,可以灵活地控制流量的平滑程度和突发程度。

在这里插入图片描述

令牌桶限流算法工作机制:

  • 令牌生成:令牌桶以恒定的速率(CIR/EIR)生成令牌,并将它们添加到桶中。如果桶已经满了,新生成的令牌将被丢弃。
  • 令牌消耗:当数据包需要发送到网络时,它们会根据自身的大小从桶中消耗相应数量的令牌。不同大小的数据包消耗的令牌数量不同。
  • 流量控制:
    如果桶中有足够的令牌,数据包将被允许发送。
    如果桶中令牌不足,数据包可能需要等待直到桶中积累了足够的令牌,或者根据配置的策略被处理(如丢弃、排队或特殊标记)。

网关层面的限流或者接口调用的限流,都可以使用令牌桶算法。
在视频、音频等多媒体数据的传输中,使用令牌桶算法来确保数据的流畅传输,同时允许一定程度的突发传输以适应网络波动。
Google的Guava和 Redisson的限流,都用到了令牌桶算法。

限流的本质是实现系统的保护,最终选择什么样的算法,一方面取决于统计的精准度要求,另外一方面要考虑限流维度和场景的要求。

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

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

相关文章

【Python程序开发系列】教你使用Docker部署一个简单的Python应用程序(案例+源码)

这是我的第313篇原创文章。 一、引言 Docker 对于程序员来说,其实和Git差不多,基本上属于一个必备工具。如果你想使用这个工具,你就必须安装这个应用工具,至于在不同操作系统上安装Docker的方式网上有很多教程,这里不…

每天五分钟深度学习:解决for循环效率慢的关键在于向量化

本文重点 上一节课程中,我们学习了多样本的线性回归模型,但是我们的伪代码实现中使用了大量的for循环,这样代码的问题是效率很低。为了克服这一瓶颈,向量化技术应运而生,成为提升程序执行效率、加速数据处理速度的重要手段。 向量化技术概述 向量化(Vectorization)是…

MySQL-核心知识要点

1、索引的数据结构-Btree BTree的优势: B树的内节点无data,一个节点可以存储更多的K-V对。在构造树时,需要的内节点会更少,那么树的层级也会越低。查询一条数据时,1. 扫描的层级低,扫描过的节点更少&…

【netty系列-04】反应堆模式的种类和具体实现

Netty系列整体栏目 内容链接地址【一】深入理解网络通信基本原理和tcp/ip协议https://zhenghuisheng.blog.csdn.net/article/details/136359640【二】深入理解Socket本质和BIOhttps://zhenghuisheng.blog.csdn.net/article/details/136549478【三】深入理解NIO的基本原理和底层…

数字化转型中,数字化如何重塑中小企业发展力?

引言:当前,我国中小微企业数字化转型处于“不平衡、不充分、不规范”阶段,普遍面临“不会转”“不能转”“不敢转”的困境。数字化转型可以帮助企业突破这些困境,实现更大的发展。更进一步,数字化转型是中小企业高质量…

学习笔记——动态路由——IS-IS中间系统到中间系统(基本概念)

二、IS-IS基本概念 1、IS-IS概述 IS-IS是ISO定义的OSI协议栈中的无连接网络服务(ConnectionLess Network Service,CLNS)的一部分,IS-IS是一种链路状态路由协议,IS-IS与OSPF在许多方面非常相似,例如,运行IS-IS协议的直…

4.BeanFactory

可以看出BeanFactory表面上只有getBean相关的方法。 实际上控制反转、基本的依赖注入、Bean的生命周期的各种功能,都是由BeanFactory的实现类来实现的。(DefaultListableBeanFactory) DefaultListableBeanFactory管理单例对象DefaultSinglet…

杨万里,诚斋体的开创者

杨万里,字廷秀,号诚斋,生于南宋绍兴元年(公元1127年),卒于南宋庆元二年(公元1206年),享年79岁。在中国古代文学的璀璨星河中,南宋诗人杨万里以其清新脱俗、贴…

Android- Framework 非Root权限实现修改hosts

一、背景 修改system/etc/hosts,需要具备root权限,而且remount后,才能修改,本文介绍非root状态下修改system/etc/hosts方案。 环境:高通 Android 13 二、方案 非root,system/etc/hosts只有只读权限&…

机器学习python实践——关于管道模型Pipeline和网格搜索GridSearchCV的一些个人思考

最近在利用python跟着指导书进行机器学习的实践,在实践中使用到了Pipeline类方法和GridSearchCV类方法,并且使用过程中发现了一些问题,所以本文主要想记录并分享一下个人对于这两种类方法的思考,如果有误,请见谅&#…

【微服务】微服务之Feign 与 Ribbon

文章目录 强烈推荐引言优点Feign示例什么是Ribbon?Ribbon 的优点Netflix Feign 和 Ribbon整合Feign 与 Ribbon 的关系Feign 与 Ribbon 结合使用的示例配置文件(application.yml)说明: Feign 与 Ribbon 结合使用的应用场景1. 动态服…

物联网的技术和应用有哪些?

随着科技的飞速发展,物联网已经成为连接世界的重要纽带,塑造着我们未来的生活。我们一起深入探索物联网的前沿技术和前瞻性应用,一窥未来的可能性。 获取物联网解决方案,YesPMP平台一站式物联网开发服务。 提示:智慧家…

图形的搭建

例一: 输入描述: 多组输入,一个整数(2~20),表示输出的行数,也表示组成“X”的反斜线和正斜线的长度。 输出描述: 针对每行输入,输出用“*”组成的X形图案。 示例一&…

爬数据是什么意思?

爬数据的意思是:通过网络爬虫程序来获取需要的网站上的内容信息,比如文字、视频、图片等数据。网络爬虫(网页蜘蛛)是一种按照一定的规则,自动的抓取万维网信息的程序或者脚本。 学习一些爬数据的知识有什么用呢&#x…

IPIDEA代理IP助力高效数据采集

IPIDEA代理IP助力高效数据采集 文章目录 IPIDEA代理IP助力高效数据采集📑前言一、爬虫数据采集痛点二、代理IP解决爬虫痛点2.1 为什么可以2.2 选择代理IP的关键因素 三、IPIDEA海外IP代理的优势3.1 IPIDEA的显著优势3.2 IPIDEA的代理类型及应用 四、IPIDEA爬虫实战4…

Fragment+Viewpage2+FragmentStateAdapter实现滑动式标签布局

大家好,我是网创有方,今天记录下标签布局的实现方法,先看下效果图。 第一步:编写一个activity或者fragment。内含有一个viewpager2的适配器,适配器类型为FragmentStateAdapter。 ​ public class MediaCreateFragment…

VideoView视频组件

简介 VideoView 在Android中是一个用户界面组件,它允许开发者在Android设备的屏幕上播放视频文件。它是Android SDK的一部分,位于android.widget包中。VideoView提供了一种简单的方法来嵌入和控制视频播放,包括设置视频源、开始、暂停、 seek…

CV每日论文--2024.6.27

1、Text-Animator: Controllable Visual Text Video Generation 中文标题:Text-Animator:可控视觉文本视频生成 简介:视频生成是各行业中具有重要价值但同时也极具挑战性的任务,例如在游戏、电子商务和广告领域。在文本到视频(T2V)生成中,一…

前端Bug 修复手册

1.前端长整数精度丢失问题 (1)问题 在前后端联调时,发现后端有一个接口返回的值和前端页面上展示的值不一致。 后端Java实现的接口如下,返回一个json格式的大整数 123456789123456789: 但是前端请求这个接口后&…

Spring每日面试题(day1)

目录 JavaWeb三大组件依赖注入的方式Autowire和Resurce有什么区别?Spring Boot的优点Spring IoC是什么?说说Spring Aop的优点Component和Bean的区别自定义注解时使用的RetentionPolicy枚举类有哪些值?Spring Boot自动装配原理Spring MVC工作原…