当前位置: 首页 > news >正文

Airbnb 亿级流量的限流架构

写在前面

如果你做过任何线上服务的限流,大概会写过这种代码:

ifredis.incr(f"qps:{caller}")>LIMIT:return429

按 caller 配 QPS 上限,超了直接 429。简单、有效,很多业务都是这么干的。但 Airbnb 在 Mussel(Airbnb的核心 KV 存储)上跑了几年这套方案之后,发现这在"阻止系统挂掉"这件事上是合格的,但不能让系统在压力下表现最好

这篇文章我们来讲一下,Airbnb 是怎么把 Mussel 的静态 QPS 限流重构成自适应流量管理系统,目标从防止崩溃变成压力下保留尽可能多的好流量

为什么静态 QPS 限流不够用?

先看看 Airbnb 的两个真实问题:
问题 1:请求之间的成本差异巨大。同样是一个请求,可能是读单条 row,也可能是扫 10 万条 row。它们在 QPS 计数器里都算一次

结果是什么?低成本调用方一直被限流,高成本调用方反而过得很好——因为前者很容易把 QPS 打满,后者一秒钟就发几个但是把后端打爆。

问题 2:流量分布偏斜。某个热点 key 突然被狂打,比如一个被分享出去的房源,这时候哪怕 caller 的总 QPS 没超,单个 shard 已经被打爆了

从这两个问题我们可以发现QPS 其实跟系统真实压力并没有太紧密。QPS更多是在假设每个请求成本一样、每个 key 压力均匀,但真实的场景并不会每个请求都一样,所以静态限流没法满足真实系统需要在边界附近精细调度。

RARC 按真实成本算请求

Airbnb 引入了一个叫RARC(Resource-Aware Rate Control)的机制,核心是用request unit(RU)代替 QPS 当限流单位,公式如下:

每种操作有个基础 RU,读 1、写 6,写更贵,加上 bytes 和延迟等等。权重是通过离线 load test 校准出来的,往集群里灌不同 size 的请求,观察后端的真实 CPU/IO/磁盘表现来反推权重。

每个调用方有自己的 RU 配额,按 token bucket 形式补给。一个请求执行完才知道它真实消耗了多少 RU,然后从 bucket 里扣。很类似现在一些大模型的token计费。

这套系统每个 dispatcher pod本地维护自己的 token bucket,不做跨 pod 同步。牺牲严格全局精确,省掉了一个分布式协调系统的麻烦。Airbnb 觉得客户端流量自然在多 pod 间负载均衡,统计意义上的 RU 消耗会均匀,本地 token bucket 已经够用。这样就能解决上面说的两个问题:

  • 一个 100k rows 的扫描会被记上几百 RU,正常的 small read 只记 1 RU;
  • 调用方再也不能用"我 QPS 没超"这种话术绕过限流。

load shedding 基于实时信号的负载抛弃

光有 RU 还不够,RU 只是个配额,但当系统真的被打到压力极限的时候,我们需要主动丢掉一部分请求来保住核心。这就是load shedding(负载抛弃)。Airbnb 的做法是把 load shedding 拆成三个实时信号配合:

信号 1:criticality tier(关键度分层)

系统会提供一个明确的优先级骨架,每个调用方在配置里被打成 T0~T3:

shedding 的时候先丢 T3,再丢 T2,T1 和 T0 留到最后

信号 2:latency ratio

Airbnb 会给 shard 的健康度算一个延迟指标:

ratio=p95_latency_short_window/p95_latency_long_window

比如 10s 短窗口的 p95 除以 5min 长窗口的 p95:

  • ratio ≈ 1:当前延迟跟平时差不多,正常。
  • ratio < 0.3 或 > 3:系统在剧烈变化,特别是 ratio 超过某阈值代表当前比平时慢很多,这时候就需要提高 RU 单价,来限制流量。

⚠️ 注意:这里用比率而不是绝对值是为了自适应不同 shard,有的 shard 平时本来就慢一点,比如读多冷数据的,绝对延迟阈值不通用,比率归一化掉了baseline的不同

信号 3:CoDel 队列控制

CoDel(Controlled Delay)是一个经典的网络队列管理算法,思路是看请求在队列里排队多久(sojourn time),超过阈值就主动丢请求。

Airbnb 把 CoDel 接进 Mussel 的请求队列:当队列里堆积的请求 sojourn time 超过阈值,直接丢最老的。这个跟 latency ratio 配合,能在毫秒级别检测到压力异常。

这里我给你最直接、最简洁、最不绕弯子、最一针见血的一句话总结:三个信号一起配合:tier 决定丢谁、ratio 决定涨多少价来限流、CoDel 决定什么时候必须丢。

hot-key defence 单点风暴防御

最后一类问题是 hot key,某个 key 突然被狂打,把它所在的 shard 单独打爆。Airbnb 用了三步防线:

Step 1:Space-Saving 算法做 top-k 计数

Space-Saving 是一种 streaming 算法,O(k) 内存就能近似估算key的频率。每个 dispatcher 自己跑一份,不需要全局聚合,单 pod 的视角就能识别出对自己来说的热点。

Step 2:超阈值识别为 hot

某个 key 的频率超过预设阈值,标记为 hot key,进入下一阶段处理

Step 3:进程内缓存 + request coalescing

热点 key 进进程内 LRU,TTL 大概 3 秒。同一个 key 的并发请求合并成一个真实后端请求,同时来 1000 个查同一个 key 的请求,后端只看到 1 个,其他 999 个拿同一个 result,就是 singleflight 机制。

⚠️注意:3 秒 TTL 是非常细的取舍。短了 cache hit 不够,挡不住热点风暴,长了,数据 staleness 增加,影响一致性。Airbnb 选 3 秒是因为 Mussel 的写入主流向已经走 Kafka 异步,3 秒级别的滞后对调用方影响小。这个数字不能盲抄——你的系统的可接受 staleness 决定了你自己的 TTL。

Airbnb模拟约 1M QPS 打到单个 key 上,经过这三步后,后端实际看到的流量被压到了几乎察觉不到

最后

我们把整套自适应流量管理系统从上往下捋一遍:

  1. 请求进来 →RARC估算 RU 成本 → 扣 token bucket。
  2. 同时 →hot-key 识别 + 进程内缓存合并
  3. 同时 →CoDel 监控队列 sojourn time + latency ratio 监控 shard 健康
  4. 系统压力上来 → 按criticality tier主动丢 T3/T2 流量,保住 T0/T1。

整体效果:

  • p99 在压力下更稳。
  • 真实 hot key 风暴下后端无感。
  • 不需要 oncall 半夜爬起来调 QPS

最后一条才是最重要的,自适应的本质就是把 oncall 从循环里踢出去。

参考:https://medium.com/airbnb-engineering/from-static-rate-limiting-to-adaptive-traffic-management-in-airbnbs-key-value-store-29362764e5c2

http://www.jsqmd.com/news/1098918/

相关文章:

  • 海上船舶识别数据集 渔船监测 货船识别 游艇数据集 油轮识别图像数据集 船舶类分类和测数据集 数据集第10163期 数字化智能化识别数据集
  • 【学习记录】Week3(三):灵魂注入——x86/x64 手写基础 Shellcode 实战
  • 界面控件DevExpress WPF v26.1新版系统配置要求|按需对应
  • 北邮 AI无线通信 | 基于KNN的调制模式识别(2)依托于MatlabR2023b对调制信号训练数据生成部分的仿真设计(data_generation_module)
  • 如何用ShaderGlass为Windows桌面添加实时GPU着色器效果
  • 移动端 App 测试入门(3)----Charles使用
  • Claude Code深度体验:Anthropic的编程Agent到底有多强?
  • 【小白也能轻松玩转龙虾】虾壳云一键部署极简流程,低配主机流畅运行 OpenClaw v2.7.9(附最新安装包)
  • 虚拟线程落地实战:从原理到生产级最佳实践
  • 企业 AI 落地六大深坑:预算超支、系统闲置的根因与工程化破局路径
  • 测量显微镜在半导体前道检测中的应用有哪些?
  • 告别卡顿!Performance-Fish让你的《环世界》流畅如鱼得水
  • 基于sigrity的TDR/TDT仿真设计
  • Typora插件只读模式下代码块粘贴的技术挑战与精细化权限控制方案
  • 想做 AI 时代的 FDE?先过三关:找行业、定方向、以身入局
  • 3.2 APP测试实战:功能、性能与ADB全解析
  • 【小白也能轻松玩转龙虾】虾壳云一键部署排错教程,解决 OpenClaw v2.7.9 各类启动报错(附最新安装包)
  • 企业级接口自动化测试平台MeterSphere从零搭建与CI/CD集成实战
  • 别再为Jetson Nano的USB串口乱序头疼了!手把手教你用udev规则固定ROS小车所有外设(附完整配置脚本)
  • 如何永久保存微信聊天记录?WeChatMsg为你提供免费完整的解决方案
  • 2026昆明公司注销超全攻略:材料清单、避坑误区、办理流程
  • Java国密SM4-CBC加密实战:基于BouncyCastle的完整实现与避坑指南
  • SENAITE LIMS:开源实验室信息管理系统完整实战手册
  • 卡在 FDE 入门的哪一步了?先判断该扛还是该换
  • Windows电脑直接安装安卓应用?5分钟搞定APK安装器
  • ai-vi-1
  • xhs项目架构深度解析:小红书Web API逆向工程实践
  • 战略升级!从传统定位到数字定位
  • AUTOSAR E2E Profile规范介绍
  • NcmppGui:快速解锁NCM音乐文件的完整免费指南