· 8 分钟阅读

一张新的 DynamoDB 表每秒能写多少条才会被限流?

AWS 文档写明,一张全新的 表开箱即可提供 "up to 4,000 write request units per second"。而大家至今仍在引用的那份关于实际表现的研究——Capital One 和 ScyllaDB 都链接过的那一份——测于 2019 年,那时还没有预热吞吐量,没有可配置的最大吞吐量,也没有现在的扩展规则。据我们所知,此后再没有人发表过实测。

于是我们做了一次。2026-08-27,对一张几分钟前在 us-east-1 创建的表,把提供的写入负载从每秒 1,000 个请求逐级加到 8,000 个:

提供负载实际达成被限流的请求
1,000/s1,000/s0
2,000/s2,000/s0
3,000/s3,000/s0
4,000/s4,000/s0
5,000/s4,132/s25,992
6,000/s4,131/s55,966
8,000/s4,134/s115,922

文档给出的基线成立,而且略偏保守:直到 4,000/s,服务一次拒绝都没有,随后无论我们怎么加压,都钉死在每秒 4,130 ±2 次写入。三个窗口、三种提供负载,同一个上限,误差在 0.05% 以内。读取则完全没有被限流过——我们把一张预置了数据的表推过每秒 12,700 次最终一致读取,再往上的缺口来自我们自己的客户端,而不是 DynamoDB。

一张表、一天、一个区域、约 1 KB 的项、均匀随机的键——看不到任何。这个范围就是这里每一个数字下面那行诚实的小字。本文剩下的部分讲我们是怎么测的,包括基准测试在跑通之前失败了三次,而没有一次失败是 DynamoDB 的错。

限流返回的是 400,而且它最先点名的嫌疑人是错的

撞上上限时,你拿到的错误值得细读:

ThrottlingException: Throughput exceeds the current capacity of your table or index.
DynamoDB is automatically scaling your table or index so please try again shortly.
If exceptions persist, check if you have a hot key:
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-partition-key-design.html

三点观察,全部有实测支撑:

  • 它是 HTTP 400,不是 5xx。你的重试策略和你的仪表板都得知道这一点。只重试 5xx 的客户端会把这些请求直接丢掉;只对 5xx 报警的监控会显示服务一片绿,而你三分之一的写入正在被弹回。
  • 在每个超基线窗口里,第一次限流出现在 0.9–3.8 秒处——服务在上限生效之前给你一小段宽限突发,而提供的负载越高,它咬得越早。
  • 热键提示是一句默认话术,不是诊断结论。我们的键是均匀随机的 UUID;根本没有热键。在小规模下,这条消息的头号嫌疑人就是表级上限本身。

延迟对这一切无动于衷:每个窗口里,区域内 p50 写入延迟都是 4–5 ms,无论有没有被限流。拒绝对服务来说很便宜——它不会变慢,只是说不。

你没法用一台笔记本测出这个数字

我们的第一件仪器是最显而易见的那个:马德里一台笔记本上的 Node 脚本。它干净地跑出每秒 1,000 次写入,到 2,000 就垮了——不是因为 DynamoDB 顶了回来,而是因为约 100 ms 的跨大西洋往返意味着每秒 2,000 个在途请求需要数百个并发套接字,事件循环被淹没了。服务一次限流都没有。我们测的是自己家的 Wi-Fi。

第二次尝试把执行器搬进了同一个区域,用一个 Lambda 函数。区域内往返约 5 ms,一个 3 GB 的函数以 10 ms 的 p50 干净地跑出每秒 2,000 个请求。再往上它就在 1,100/s 附近拉平,CPU 打满:请求签名和响应处理是单线程 JavaScript,一个执行器根本签不动每秒 4,000 个请求。分配的内存:3 GB。用掉的内存:253 MB。瓶颈从来不是 RAM——Lambda 的 CPU 份额随内存设置一起变大,我们买的是算力,不是存储。

所以最终的仪器是八个 Lambda 组成的机群,每个承担总提供负载的八分之一,全部对齐同一个墙钟 T0 启动,好让各自的窗口对得上。八个执行器各自轻松跑 1,000/s,就给出了 8,000/s 的提供负载还留有余量,而总量是逐个计数请求的求和——全程没有任何外推。

有一次跑通之前,三次运行死掉了,而 DynamoDB 每次都是无辜的

机群的第一次运行以某个执行器报告它在 T0 之后 882 秒才启动而告终——一个二十秒的约会迟到了十五分钟。第二次运行死于读取超时。第三次关掉了重试,八个执行器同时大声报错。与此同时,CloudWatch 显示每一个 Lambda 都干净、准时地跑完了自己四分钟的测量,没有任何错误。

罪魁祸首是笔记本与 Lambda 之间的那条连接。一次同步调用会在整个运行期间保持一条 HTTPS 连接开着、全程静默——而家用路由器会在几分钟后悄悄掐掉静默连接。CLI 看到套接字已死,做了最糟糕的那件事:它静默重试,重新跑了一个测量 Lambda,而那个 Lambda 发现自己的 T0 早已过去。一个会不声不响跑两遍的基准测试框架不是框架;它是一个附带 AWS 账单的随机数生成器。

最终跑通的那个形态有三条规则,现在我们会把它们用在任何长时间的远程测量上:

  • 发了就不管,结果走带外通道。执行器以异步方式调用(连接在几毫秒内关闭),把各自的结果作为项写进一张小的 DynamoDB 表;驱动端轮询这八行结果。没有任何连接活得比一次请求更久。
  • 重试处处关闭。测量客户端每个请求只尝试一次——一次重试就会静默吸收掉我们本就是来数的那些限流——调用路径上的重试也关掉了,所以任何执行器都不可能跑两遍。
  • 用看门狗取代卡死。每个执行器让自己的时间表与一个截止时刻赛跑;一旦哪里卡住,它就返回部分计数外加一份精确记录卡在哪里的快照,而不是在沉默中超时。一次会自我解释的失败运行只花掉一次读取;一次卡死则要花掉一个晚上。

每个请求还都带 8 秒超时。那次卡死的运行之所以卡死,是因为一个没有超时的在途请求把最后的排空步骤永久卡住了。约 400 万个请求里,一次没有上界的等待就足够了。

读取那边的表现

读取阶段跑在第二张全新的表上,表里预置了 1,000 个项,用的是 GetItem(每个约 1 KB,0.5 个读取单位):

提供负载实际达成被限流
4,000/s4,000/s0
8,000/s7,941/s0
12,000/s11,119/s0
16,000/s12,762/s0

自始至终零限流。文档给出的每秒 12,000 次读取基线成立,而我们找不到它的边界:在提供 16,000/s 时,我们八个执行器里有五个撞上了自己的客户端饱和,所以 12,762/s 这个数字是我们这套机群的天花板,不是 DynamoDB 的。我们把这一点直说,而不是把它包装成服务限制。区域内读取的 p50 是 2–4 ms。

还有两个值得记住的小数字:在这次基准测试里,一张全新的按需表从 CreateTableACTIVE 用了 22 秒,而在更早的一次探测里是 7.4 秒——按这个波动做预算,别按最好情况。另外,整场基准测试计费 672,116 次写入和 108 万次读取,一共花了 $0.97。仪器可以重复使用;这场实验只值一杯咖啡。

半小时的压力并不会让上限翻倍

AWS 的增长规则说,按需容量最多能承接你此前峰值的两倍。我们想亲眼看看,所以在上限测试之后,我们对一张表连续 34 分钟施加 8,000 写入/s 的提供负载,并按每 10 秒把实际达成速率分桶。形状是这样:

承压分钟数上限
0–8~4,000/s(基线,纹丝不动)
9–25~5,000/s
26~6,000/s
27–34~7,000/s
在 8,000/s 供给下持续 34 分钟、逐分钟的实际写入/秒

增长是以约 1,000/s 的突兀台阶到来的,不是斜坡——这一分钟平在一个速率上,下一分钟平在下一个速率上。在持续超需的整整 8 分钟里,第一个上限都黏着不动。而 34 分钟之后,这张表跑到了 7,000/s:是起点的 1.75 倍,仍然够不着提供的 8,000,也够不着干净的翻倍。如果你的上线需要一张新表提供超过约 4,000 写入/s,就提前预热它,或者显式设置它的按需最大吞吐量——增长机制是真实存在的,但它既不即时,也不会照着你的时间表慷慨行事。这个行为还很稳定:2019 年那项研究里,承受 9,000/秒供给的表在测试结束时已增长到约 7,000/秒——与我们的表七年后到达的平台一模一样。那次运行花了 $12.67,是我们那一整天最贵的一件事。

如果你要自己测量一项云服务,有哪些经验可以借鉴

  • 把负载生成器放到和目标同一个区域。否则你测的是自己的网络路由,不是那项服务。
  • 一个 Node 进程无论给多少内存,都在每秒约 2,000 个签名请求处封顶;把负载分片给多个执行器,再把计数结果求和。
  • 在测量路径的每一层都关掉重试。重试存在的意义是掩盖,而基准测试存在的意义正是看清同一样东西。
  • 绝不要在一次长时间运行中保持一条静默连接。异步调用,走带外通道交付结果,然后轮询。
  • 给每个请求一个超时,给每个执行器一个看门狗——卡住时返回部分数据外加卡住状态的快照。
  • 给每个执行器设一个硬性的操作上限,好让节奏控制的 bug 直接中止而不是把账单跑起来,并在 finally 里拆掉这次运行创建的一切——表、角色、函数、日志。

这份数据喂给了哪些参考页面

完整数据集——每个窗口、每个执行器、各项延迟分位数、逐字的错误字符串——现在支撑着我们 DynamoDB 限制参考里的实测表格,与我们更早发布的项大小和分页上限探测并列。如果你每天都和 DynamoDB 打交道,DynoTable 是我们为它做的桌面客户端——同一个团队,同样的习惯:在复述任何说法之前,先拿实时服务核对一遍。

无需控制台即可使用 DynamoDB

一款快速的 DynamoDB 桌面客户端,可运行 DynamoDB 无法执行的真正 SQL——JOINs、GROUP BY、聚合——并支持可视化编辑和运行在你自己的 Bedrock 密钥上的 AI agent。

30 天免费试用,无需信用卡 — 之后为无时间限制的免费版。