news 2026/5/7 0:59:35

面试官:限流是什么?如何实现?许多人答错。

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
面试官:限流是什么?如何实现?许多人答错。

在高并发架构中,限流是保障服务高可用的“安全阀”。当上游流量洪峰超出下游服务的处理极限时,限流机制通过精准的拒绝、排队或延迟策略,防止系统因资源耗尽而发生雪崩。

本文将从限流的分类入手,深入剖析单机限流的核心算法逻辑,并详解分布式全局限流的两种主流架构,为你构建一套完整的限流知识体系。

为什么需要限流?

在分布式系统中,限流(Rate Limiting)是下游服务为了防止被上游请求压垮,而采取的一种自我保护机制。

目标:控制请求速率,保证系统稳定性

分类:

  • 频控:控制用户在N秒内只可执行M次操作。

  • 单机限流:某服务的每台服务器在1s内最多可处理"个请求。

  • 全局限流:某服务在1s内总共可处理M个请求。

  • 单机自适应限流:某服务的每台服务器根据自身服务状况,使用各种自动化算法动态判断是否限制请求。

频控

用户维度下的限流

场景:频控主要用于防止恶意刷接口或限制用户行为。

N秒内只能执行1次

实现原理:使用SETNX命令。如果设置成功,说明是首次操作;如果失败,说明在时间窗口内已操作过。

// 对应 Redis 命令: SET key 0 EX 30 NX Boolean result = redisTemplate.opsForValue().setIfAbsent(key, 0, 30, TimeUnit.SECONDS);

N秒内最多执行 M 次

当涉及到“计数”和“过期时间设置”两个动作时,必须保证原子性,否则可能出现 Key 永久存在或计数错乱。

实现逻辑:使用INCR计数,当返回值为 1 时设置过期时间。

判断逻辑:

  • count ≤ M → 放行

  • count > M → 限流

local count = redis.call('INCR', KEYS[1]) if count == 1 then redis.call('EXPIRE', KEYS[1], ARGV[1]) -- ARGV[1] 为过期秒数 end return count

单机限流

控制“单台机器”的处理能力

固定时间窗口

原理:将时间轴切分为固定长度的窗口(如1s),每个窗口维护一个计数器。

执行流程:

  • 定位窗口:根据当前时间戳,计算出所属的窗口ID(例如当前秒数)。

  • 获取计数器:从内存中获取该窗口ID对应的计数器。

  • 判断与扣减:

    • 如果计数器值 > 0:计数器减1,允许请求通过。

    • 如果计数器值 = 0:拒绝请求。

缺点:无法防止时间窗口边界附近的流量暴增。

举例:假设限制1s内100个请求。在0.9s时涌入100个请求,在1.1s时又涌入100个请求。虽然每个窗口都没超限,但在1.0s前后的200ms内,系统实际承受了200个请求,导致瞬间流量翻倍。

滑动时间窗口

原理:将时间窗口划分为更小的格子。窗口随着时间滑动,丢弃过期的槽位,累加新槽位的计数。

流程:

  1. 划分时间槽:将时间线按小粒度(如50ms)划分为独立的时间槽。

  2. 定义滑动窗口:限流窗口由最近的N个槽(如20个)组成,随时间推移不断向后滑动。

  3. 请求判定:

    1. 当请求到来时,在当前窗口内查找是否存在计数大于0的槽。

    2. 若找到:将该槽计数减1,允许请求通过。

    3. 若未找到(所有槽计数均为0):丢弃请求,触发限流。

优点:解决了窗口边界流量暴增问题,精度更高。

缺点:但需要维护更多的槽位数据,内存和CPU开销相对较大。

漏桶算法

原理:请求像水一样流入桶中,桶以恒定的速率出水(处理请求)。无论流入速率多快,流出速率永远固定。

执行流程:

  1. 请求到达:检查漏桶(队列)是否已满。

  2. 判断与入队:

    1. 如果桶未满:将请求加入队列尾部,等待处理。

    2. 如果桶已满:直接拒绝请求。

  3. 匀速处理:一个独立的消费者线程以固定的时间间隔(如每10ms)从队列头部取出一个请求进行处理。

特点:强行整形,将突发流量平滑为恒定流量,按照固定的速率被处理。

缺点:无法应对突发流量。

令牌桶算法

原理:系统以恒定速率向桶中放入令牌,桶有容量上限。存满新生成的令牌会被丢弃,请求处理前必须先获取令牌,无令牌则拒绝。

适用场景:对流量精度高,并且容忍短期突发流量。

优点:既控制长期的平均速率,又支持短期突发流量。

缺点:实现复杂度较高。(要维护令牌的生成,存储,消耗)

全局限流

基于Redis的集中式限流

不适合请求量巨大的服务

逻辑:把单机的固定窗口计数器搬到 Redis 上。

流程:所有服务器实例在处理请求前,先去 Redis 做一次INCR。如果 Redis 返回的值超过总限额,本地拦截。

优点:数据强一致,限流精准。

缺点:引入额外网络调用,Redis本身可能成为性能瓶颈,影响了业务服务的稳定性。

基于时间片的动态反馈限流

适合请求量大的服务,对请求进行粗略筛选。

核心逻辑:上报统计 -> 计算比例 -> 下发丢弃率。

流程:

  1. 统计上报:各服务实例周期性(如每1s)将本地的请求数、延迟等统计信息上报到消息队列。

  2. 全局聚合:日志收集器消费消息,计算整个集群在当前时间片的实际QPS。

  3. 决策下发:限流服务器对比实际QPS与目标阈值,计算丢弃率(DropRate)。

    1. 公式:DropRate = (实际QPS - 目标QPS) / 实际QPS

  4. 本地执行:各实例接收最新的DropRate,在本地进行概率性丢弃。

优点:避免了每次请求都访问Redis,性能极高。

缺点:存在秒级的控制延迟,无法做到毫秒级的精准控制,适合对实时性要求不苛刻的场景。


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/12 1:39:47

工业相机选型必看:眼在手上vs眼在手外的标定差异全解析

工业相机选型实战:眼在手上与眼在手外的标定差异深度剖析 当机械臂需要精准抓取流水线上的零件时,视觉系统就像它的"眼睛"。但这双眼睛的安装位置不同,会直接影响整个系统的标定难度和工作效率。想象一下外科医生的手术场景——显微…

作者头像 李华
网站建设 2026/4/12 2:57:26

Qwen3.5-2B轻量部署对比:Qwen3.5-2B vs Qwen3.5-8B在端侧设备资源占用实测

Qwen3.5-2B轻量部署对比:Qwen3.5-2B vs Qwen3.5-8B在端侧设备资源占用实测 1. 引言:轻量化多模态模型的价值 在边缘计算和端侧AI应用快速发展的今天,如何在有限的计算资源下部署强大的多模态模型成为关键挑战。Qwen3.5-2B作为Qwen3.5系列的…

作者头像 李华
网站建设 2026/4/12 7:25:07

Bagging与Boosting的实战对比:如何选择适合的集成学习方法

1. 从决策树到集成学习:为什么需要Bagging和Boosting? 记得我第一次用决策树做分类任务时,发现模型在训练集上表现完美,但测试集上却惨不忍睹。这种过拟合问题困扰了我很久,直到发现了集成学习这个"外挂"。简…

作者头像 李华
网站建设 2026/4/11 16:36:47

QQ截图独立版终极指南:高效截图与OCR文字提取的完整解决方案

QQ截图独立版终极指南:高效截图与OCR文字提取的完整解决方案 【免费下载链接】QQScreenShot 电脑QQ截图工具提取版,支持文字提取、图片识别、截长图、qq录屏。默认截图文件名为ScreenShot日期 项目地址: https://gitcode.com/gh_mirrors/qq/QQScreenShot QQ截…

作者头像 李华
网站建设 2026/4/11 23:09:31

终极指南:使用Elden-Ring-Debug-Tool解锁艾尔登法环全部潜能

终极指南:使用Elden-Ring-Debug-Tool解锁艾尔登法环全部潜能 【免费下载链接】Elden-Ring-Debug-Tool Debug tool for Elden Ring modding 项目地址: https://gitcode.com/gh_mirrors/el/Elden-Ring-Debug-Tool 你是否想在《艾尔登法环》中自由探索交界地的每…

作者头像 李华