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

news2024/11/17 21:56:59

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

常见的限流算法有:

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

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.coloradmin.cn/o/1884393.html

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

相关文章

LeetCode题练习与总结:二叉树的前序遍历--144

一、题目描述 给你二叉树的根节点 root ,返回它节点值的 前序 遍历。 示例 1: 输入:root [1,null,2,3] 输出:[1,2,3]示例 2: 输入:root [] 输出:[]示例 3: 输入:roo…

ARM功耗管理软件之DVFSAVS

安全之安全(security)博客目录导读 思考:功耗管理软件栈及示例?WFI&WFE?时钟&电源树?DVFS&AVS? 目录 一、ARM功耗管理软件之DVFS 二、ARM功耗管理软件之AVS 一、ARM功耗管理软件之DVFS 有一个实现特定…

招生报名系统教培招生小程序

招生报名系统:轻松实现教培招生新高度 🚀 招生报名系统,开启智慧教育新时代 在当今数字化快速发展的时代,教育行业也迎来了变革的浪潮。招生报名系统作为这一变革的先锋,为教育机构提供了全新的招生渠道和管理方式。通…

jmeter-beanshell学习1-vars使用获取变量和设置变量

最近又开始了用jmeter做自动化,不管怎么实现,都逃离不了用beanshell,最后把所有校验都放在了beanshell判断,效果还不错。 首先jmeter有很多beanshell相关的元件,取样器、前置处理器、后置处理器、断言,暂时…

传输距离3000M|低延迟|48K采样音频传输模块-SA356大功率发射模块

无线音频应用中,远距离音频传输在许多领域具有广泛的应用需求,例如大型会议系统、公共广播、户外活动和音乐演出等。为了满足这些需求,音频传输模块需要具备一些关键特性,包括长距离传输能力、高音质、低延迟、稳定性以及抗干扰能…

UE5 动画蓝图

文章目录 一、State Machines二、Blend Spaces三、Aim Offset四、Montage 初步介绍 Unreal Engine 5 Tutorial - Animation Blueprint Part 1: State Machines (youtube.com) Unreal Engine 5 Tutorial - Animation Blueprint Part 2: Blend Spaces (youtube.com) Unreal Engi…

RK3568平台(USB篇)TYPE-C接口与PD协议

一.TYPE-C接口简介 type-c 插座: type-c 插头: type-c 线缆: type-c 接口定义之插座: type-c 硬件原理图: VBUS:供电引脚,用于传输电源电压,一般为5V或12V。 GND:地引…

类与对象(3)

1.首先我们先介绍一下 赋值重载 我们来举个例子来实现一下 赋值重载也叫赋值拷贝 void operator(const Date& d){//赋值拷贝 是拷贝给一个已经赋值好的对象 也叫赋值重载cout << "赋值重载" << endl;year d.year;month d.month;day d.day;} 如果…

Linux 高级编程——线程控制

线程控制&#xff1a;互斥与同步 概念&#xff1a; 互斥 》在多线程中对临界资源的排他性访问。 互斥机制 》互斥锁 》保证临界资源的 访问控制。 pthread_mutex_t mutex; 互斥锁类型 互斥锁变量 内核对象 框架&#xff1a; 定义互斥锁 》初始化锁 》加…

uniapp中如何进行微信小程序的分包

思路&#xff1a;在uniapp中对微信小程序进行分包&#xff0c;和原生微信小程序进行分包的操作基本上没区别&#xff0c;主要就是在pages.json中进行配置。 如图&#xff0c;我新增了一个包diver-page 此时需要在pages.json中的subPackages数组中新增一项 root代表这个包的根…

“论单元测试方法及应用”精选范文,软考高级论文,系统架构设计师论文

论文真题 1、概要叙述你参与管理和开发的软件项目,以吸你所担的主要工作。 2、结给你参与管理和开发的软件项目&#xff0c;简要叙述单元测试中静态测试和动态测试方法的基本内容。 3、结给你惨与管理和研发的软件项目,体阐述在玩测试过程中,如何确定白盒测试的覆盖标准,及如…

Sourcecodester Fantastic Blog CMS v1.0 SQL 注入漏洞(CVE-2022-28512)

前言 CVE-2022-28512 是一个存在于 Sourcecodester Fantastic Blog CMS v1.0 中的 SQL 注入漏洞。攻击者可以通过 "/fantasticblog/single.php" 中的 id 参数注入恶意 SQL 查询&#xff0c;从而获得对数据库的未经授权的访问和控制。 漏洞详细信息 漏洞描述: 该漏…

QML学习——Qt Quick Extras Examples 1.4(八)

Qt Quick Extras Examples 阅读官方的源码然后尝试做了下 01 A car dashboard 样例演示&#xff1a; 说明&#xff1a; ValueSource组件控制数值相关的动画&#xff0c;例如图中数值的变化&#xff1b;TurnIndicator组件是控制左右方向灯的闪烁和背景&#xff0c;里面使用…

深入解析HDFS:定义、架构、原理、应用场景及常用命令

引言 Hadoop分布式文件系统&#xff08;HDFS&#xff0c;Hadoop Distributed File System&#xff09;是Hadoop框架的核心组件之一&#xff0c;它提供了高可靠性、高可用性和高吞吐量的大规模数据存储和管理能力。本文将从HDFS的定义、架构、工作原理、应用场景以及常用…

【Kotlin】Kotlin 基础语法指南

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…

vue项目手机录音

手机实现录音功能&#xff0c;安卓和苹果都可。功能&#xff0c;点击开始录制录音后&#xff0c;随时可以停止录音&#xff0c;如果不点击停止最多录制15秒。 页面结构 <!--音频--> <div class"audio-box"><audio id"audioPlayer"controlsc…

excel修改批量一列单价的金额并保留1位小数

1.打开表格&#xff0c;要把单价金额变成现在的两倍&#xff0c;数据如下&#xff1a; 2.把单价这一列粘贴到一个新的sheet页面&#xff0c;在B2单元格输入公式&#xff1a;A2*2 然后按enter回车键,这时候吧鼠标放到B2单元格右下角&#xff0c;会出现一个黑色的小加号&#xf…

泰国火出圈的slots游戏联动本土网盟广告推广优势

泰国火出圈的slots游戏联动本土网盟广告推广优势 在泰国&#xff0c;Slots游戏凭借其独特的魅力和吸引力&#xff0c;迅速成为玩家们的热门选择。然而&#xff0c;要在竞争激烈的市场中脱颖而出&#xff0c;推广策略显得尤为重要。本土网盟广告以其独特的优势&#xff0c;为Sl…

制氢厂氢气泄漏安全监测:氢气传感器守护“氢”安全

随着全球能源结构的转型和清洁能源的需求日益增长&#xff0c;氢能作为一种高效、清洁的能源载体&#xff0c;受到了广泛关注。制氢厂作为氢能产业的重要组成部分&#xff0c;其安全问题也日益凸显。在制氢过程中&#xff0c;氢气泄漏是潜在的安全隐患之一&#xff0c;因此&…

数据结构/作业/2024/7/11

1.在堆区申请两个长度为32的空间&#xff0c;实现两个字符串的比较【非库函数实现】 #include <stdio.h> #include <stdlib.h> void input(char*p); void my_strcmp(char *p1,char *p2); int main(int argc, const char *argv[]) {//申请内存空间32个字节 char *p…