阿珍在 AWS 云上开了一家数字大排档,把菜单、订单、会员卡全部存进一张叫 DynamoDB 的神奇表格里。这张表格是一座全天候智能厨房:你不需要亲自洗菜切菜,只要把食材(数据)递进去,它就能按你的要求出菜。可这座厨房不收“包月随便吃”的会员费,而是给了你两条计费路线:要么按客人点的每一道菜付费(按需模式),要么提前租下一整队厨师、不管开不开张都发工资(预置模式)。生意清淡时选前者省钱,客流稳定时选后者更划算。为了让厨房既不浪费也不忙乱,你还能请一位“调度经理”(自动伸缩)在客流增减时自动调整厨师数量。阿珍后来发现,排座的方式(分区键设计)也决定出菜快慢——如果所有客人都挤第一排桌子,再多厨师也会忙得团团转。隔壁老陈还有一家叫 Cassandra 的自助烧烤摊,菜单相似,经营方式却完全不同。这篇指南,就带你把这笔账彻底算明白。

岗位关联

容量模式和计费是 DynamoDB 成本优化的命门:理解它,你才能在 AWS 上花最少的钱扛住最大的流量,这是数据库工程师进阶的必修课。

目录
  1. 可视化演示
  2. 容量模式总览
  3. 按需计费机制
  4. 预置计费机制
  5. 自动伸缩策略
  6. 分区键设计
  7. 与Cassandra对比
  8. 选型优化成本
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

动态演示DynamoDB的核心机制,通过基础/核心/应用/扩展四种模式展示关键概念与交互流程。

本节配有交互动效(进入视口后自动加载,约 3KB)。

DynamoDB:按需与预 按需与预置容量模式对比 RCU与WCU计费模型解析 核心机制可视化 DynamoDB整体架构与关键组件

容量模式总览

刚开店时,阿珍根本不知道每天会来多少客人。她选了“按单付费”:每个客人点一份餐,系统就记一笔钱,没人来的时候一分钱都不用花。客人多就多付,客人少就少付,账单完全跟着流量走——这就是 DynamoDB 的按需模式(on-demand)。另一种是预置模式(provisioned):提前租好一整队厨师和传菜员,约定“每秒最多出多少菜”,无论有没有客人,工资都照发。

切换到技术语言:DynamoDB 把数据读取比作传菜,把数据写入比作炒菜。按需模式下,AWS 自动保证后厨随时有资源,你只需要为实际消耗的读写请求单位付费;预置模式下,你需要明确设置每秒的读容量(RCU)和写容量(WCU),AWS 按小时向你收“固定租金”。选择哪种模式,最重要的指标是容量利用率——预置容量到底被用掉了多少:

AWS 允许表在两种模式之间切换,但限制每个自然日的切换次数有限(通常不超过两次,以官方最新文档为准)。切换过程不丢数据、不中断服务,只是计费规则变了。按需模式适合流量波动剧烈、难以预测的场景,比如新应用上线、突发营销活动;预置模式适合流量平稳、规律可预测的业务。

阿珍总结:按单付是“随缘经营”,包月是“固定班底”。生意难测时就随缘,摸清客流规律之后再换包月,能省下不少冤枉钱。

U=AP×100%U = \dfrac{A}{P} \times 100\%
利用率就是“实际消耗 ÷ 预置容量”。利用率越高,说明你花的包月钱越值;利用率低,说明厨师在吃闲饭。
  1. A(实际消耗)后厨真正端出去的菜量,也就是每秒实际消耗的读写容量单位,来自 CloudWatch 的消费指标。
    A=每秒实际消耗容量单位A = \text{每秒实际消耗容量单位}
  2. P(预置容量)你提前签约的“出菜能力”,也就是每秒预配置的容量单位数。
    P=每秒预置容量单位P = \text{每秒预置容量单位}
  3. ×100%把比例换算成百分比,方便和目标利用率(如 70%)做比较。
    百分比=比值×100%\text{百分比} = \text{比值} \times 100\%

按需计费机制

自助餐厅的规则是“一碟菜大小决定价格”。阿珍发现,客人点一条小黄鱼(1KB 的数据)和点一整只烤全羊(50KB 的数据),后厨的辛苦程度完全不同。DynamoDB 也一样,它不看“存储了几条数据”,而看“每条数据有多大、被读写过多少次”。

具体来说,DynamoDB 用两个标准单位来计费:读请求容量单位 RCU(read capacity unit)和写请求容量单位 WCU(write capacity unit)。1 个 WCU 支持每秒写入最多 1KB 数据;1 个 RCU 支持每秒强一致读取最多 4KB 数据(弱一致读可以读 8KB,相当于打了五折)。一个数据项消耗多少个单位,是由它的大小决定的:

按需模式的账单就是所有读请求的 RCU 合计乘以单价(约每百万个 0.25 美元),加上所有写请求的 WCU 合计乘以单价(约每百万个 1.25 美元)。它没有最低消费、没有预留费,一切按实际发生量计费。这也意味着,只要把数据项做小,比如字段精简、避免存超大嵌套文档,就能直接降低每一笔请求的单价。

阿珍觉得按需账单就像水电费:没人住的时候水表不走字,心里踏实;但单价确实比“包年套餐”贵一些。所以它最适合试营业期、流量忽高忽低的阶段。

RCU=⌈S项4 KB⌉,WCU=⌈S项1 KB⌉\text{RCU} = \left\lceil \dfrac{S_{\text{项}}}{4\text{ KB}} \right\rceil,\qquad\text{WCU} = \left\lceil \dfrac{S_{\text{项}}}{1\text{ KB}} \right\rceil
数据项越大,消耗的容量单位越多。写 5KB 的数据要付 5 个 WCU 的钱,读 8KB 的数据要付 2 个 RCU 的钱。
  1. S\_项(数据项大小)单条项目的大小,这里是计费的地基。大排档里一只烤全羊自然比一碟花生米贵。
    S项=单条数据的大小(KB)S_{\text{项}} = \text{单条数据的大小(KB)}
  2. 4KB 的读阈值1 个 RCU 最多容纳 4KB 的强一致读。数据小于等于 4KB 按 1 个 RCU 算,超过一点就按 2 个算。
    RCU=⌈S项4 KB⌉\text{RCU} = \left\lceil \dfrac{S_{\text{项}}}{4\text{ KB}} \right\rceil
  3. 1KB 的写阈值1 个 WCU 最多容纳 1KB 的写入。写入是更贵的“炒菜”,单位更小、计价更细。
    WCU=⌈S项1 KB⌉\text{WCU} = \left\lceil \dfrac{S_{\text{项}}}{1\text{ KB}} \right\rceil
  4. 向上取整 ⌈⌉哪怕只超 0.1KB,也要按下一个整数单位付钱,就像出租车跳表。
    ⌈x⌉=大于或等于 x 的最小整数\lceil x \rceil = \text{大于或等于 } x \text{ 的最小整数}

预置计费机制

客流稳定之后,阿珍改成了“包月雇厨师”:固定雇 60 位厨师和 200 位传菜员,无论下雨打烊还是排队长龙,工资都照发。包月的单价更便宜,但她的账本上从此多了一笔雷打不动的“硬支出”。这就是预置模式:你为表设置每秒的读写容量,AWS 按小时计费,不管实际用了多少。

预置模式的月度成本由两个数字决定:预置的 RCU 数量和预置的 WCU 数量。以写为例,每 WCU 小时约 0.00065 美元,每 RCU 小时约 0.00013 美元,一个月按 730 小时估算。同时,DynamoDB 还允许你把“没来得及用的能力”存起来,最多积攒 300 秒,在突发时一次性借出,这就是突发容量:

一旦超过预置容量,DynamoDB 不会让请求安静地排队,而是直接“请你稍等”——返回节流错误(ProvisionedThroughputExceededException)。客户端必须做指数退避重试,否则订单就会丢失。所以预置容量不是设得越高越好,也不是越低越省,而是要在“够用”和“不浪费”之间找平衡。

阿珍说,包月模式让她养成了“看表炒菜”的习惯:平时压着容量跑,短时爆单靠突发额度硬扛,长期不够就赶紧联系 AWS 加人——否则后厨会礼貌地拒绝上菜。

C_{\text{月}} = (R_p \times 0.00013 + W_p \times 0.00065) \times 730,\qquadE_{\text{突发}} = 300 \times W_p
预置费用是“月固定工资”,突发容量是“最多能临时借的加班时长”。借来的能力用完还不够,就要被节流了。
  1. R\_p(预置读容量)你为表承诺的每秒 RCU 数,决定传菜员人数。
    Rp=每秒预置读容量R_p = \text{每秒预置读容量}
  2. W\_p(预置写容量)你为表承诺的每秒 WCU 数,决定厨师人数。
    Wp=每秒预置写容量W_p = \text{每秒预置写容量}
  3. 小时费率每 RCU 小时约 0.00013 美元,每 WCU 小时约 0.00065 美元,不同区域略有浮动。
    写单价=5×读单价\text{写单价} = 5 \times \text{读单价}
  4. 730 小时一个月大约 730 小时,由 365 天乘以 24 小时再除以 12 个月得到。
    730=365×2412730 = \dfrac{365 \times 24}{12}
  5. 突发额度最多能借出 300 秒未使用的容量,用来应付短时尖峰。
    E突发=300×WpE_{\text{突发}} = 300 \times W_p

自动伸缩策略

总是手动调厨师太累,阿珍雇了一位“调度经理”。他时刻盯着大堂的排队人数,客人多了就临时加厨师,客人少了就裁掉几个,让工资账单跟着客流起伏。这位经理在 DynamoDB 里叫自动伸缩(Auto Scaling),它使用的策略叫“目标追踪”。

原理很简单:你告诉系统一个目标利用率(默认 70%),再设定容量上下限。系统持续监控“实际消耗容量 ÷ 当前预置容量”,一旦发现消耗超过目标,就按比例把预置容量往上调;反过来,如果利用率长期偏低,就往下调。扩容的目标值由下面的公式决定:

自动伸缩不是瞬间完成的,它需要若干个评估周期(比如 1 分钟粒度)才能生效。因此它适合应对“缓慢起伏”的稳态波动,扛不住“一秒之内暴涨”的极端尖峰。要想防秒杀,还得多留余量,或者干脆用按需模式。另外,配置自动伸缩还需要在 IAM 里授权,让 DynamoDB 有权限帮你调整吞吐量。

调度经理不是魔术师,数人头、写排班表都需要时间。但有了他,阿珍的工资账单终于第一次跟着客流上下起伏,而不是永远一个样。

C新=⌈C消耗U目标⌉C_{\text{新}} = \left\lceil \dfrac{C_{\text{消耗}}}{U_{\text{目标}}} \right\rceil
假如当前每秒消耗 90 个 WCU,目标利用率是 70%(0.7),系统就会把容量调到 90÷0.7≈129 个 WCU,留出 30% 的余量。
  1. C\_消耗(当前消耗)此刻每秒真正用掉的容量单位,由 CloudWatch 的 ConsumedCapacity 指标提供。
    C消耗=每秒实际消耗容量C_{\text{消耗}} = \text{每秒实际消耗容量}
  2. U\_目标(目标利用率)你希望预置容量被用到几成,默认 0.7,也就是留三成缓冲给突发流量。
    U目标=0.7U_{\text{目标}} = 0.7
  3. 向上取整容量单位必须是整数,所以算出 128.6 也要变成 129。
    ⌈900.7⌉=129\left\lceil \dfrac{90}{0.7} \right\rceil = 129

分区键设计

厨房里有 100 张桌子,每张桌子就是 DynamoDB 里的一个分区。数据坐哪张桌子,由分区键(partition key)决定。阿珍一开始图省事,用“下单时间”当分区键,结果每晚八点所有订单都挤进第一张桌子,其他桌子空转,传菜员全部堵在过道——这就是典型的热点键问题。

好的分区键要满足两个条件:取值多(高基数),访问均匀。比如用户 ID、订单 ID、设备 ID 都很合适;而时间戳、地区编号这类取值少或分布偏斜的字段,容易让某一两个分区承担绝大部分流量。每个分区还有硬性吞吐上限:最多支持 1000 WCU/s 或 3000 RCU/s,超出就会被节流。一张表需要多少个分区,取决于总吞吐和单分区上限:

除了分区键,DynamoDB 还允许设置排序键(sort key),让同一分区内的数据按某种顺序排列,方便范围查询,例如“同一个用户 ID 下的订单按时间排序”。设计时尽量让访问均匀落到所有分区,写密集场景尤其要避免使用顺序递增的键(如自增 ID、纯时间戳),否则最新数据永远打在最后一个分区上。

阿珍把分区键换成用户 ID 之后,订单像客人均匀落座一样分散到各个包间,每张桌子都热闹但井然有序,厨房的效率一下子提升了好几倍。

N分区=⌈max⁡(W总1000, R总3000)⌉N_{\text{分区}} = \left\lceil \max\left(\dfrac{W_{\text{总}}}{1000},\ \dfrac{R_{\text{总}}}{3000}\right) \right\rceil
表的总吞吐越大,分区越多。写密集型表按“每分区 1000 WCU”算,读密集型表按“每分区 3000 RCU”算,取两者中更苛刻的那个。
  1. W\_总(总写吞吐)整张表每秒需要的写入容量总和,单位 WCU/s。
    W总=全表写吞吐W_{\text{总}} = \text{全表写吞吐}
  2. 1000(分区写上限)单个分区最多承载 1000 WCU/s,超过就得加分区。
    单分区写上限=1000 WCU/s\text{单分区写上限} = 1000\ \text{WCU/s}
  3. R\_总(总读吞吐)整张表每秒需要的读取容量总和。
    R总=全表读吞吐R_{\text{总}} = \text{全表读吞吐}
  4. 3000(分区读上限)单个分区最多承载 3000 RCU/s,读密集时这是瓶颈。
    单分区读上限=3000 RCU/s\text{单分区读上限} = 3000\ \text{RCU/s}
  5. max 与向上取整分别算出的分区需求取较大者,再向上取整,保证读写都不超限。
    N分区=⌈max⁡(⋅)⌉N_{\text{分区}} = \left\lceil \max(\cdot) \right\rceil

与Cassandra对比

隔壁老陈卖了好几年烤肉饭,配方和 DynamoDB 有些像:都是键值/宽列风格的 NoSQL 数据库。但老陈选择自己开摊——他自建了一个叫 Cassandra 的烧烤摊集群。两者的区别,核心在“经营方式”:DynamoDB 是 AWS 全托管,服务器、备份、扩缩容全由平台负责;Cassandra 是自建开源软件,节点、修复、压缩、升级全得自己操心。

一致性模型是两者最重要的差异之一。DynamoDB 默认提供最终一致读,也可以显式请求强一致读;Cassandra 则提供可调一致性,每次读写都可以指定 ONE、QUORUM、ALL 等级别。理解 Cassnadra 的仲裁机制,可以用一个经典不等式:

运维上,DynamoDB 几乎免运维,但会和 AWS 生态深度绑定;Cassandra 可以部署在任何机房、避免厂商锁定,但要自己承担集群故障、数据修复和版本升级的长期成本。选型建议:如果你已经在 AWS 上、追求省心省力,选 DynamoDB;如果必须跨云或私有化部署、需要灵活的自定义查询(如 CQL 宽表聚合),选 Cassandra 更合适。

阿珍最后想明白:两家店卖的都是“烤肉饭”,但一个是点外卖(托管服务),一个是自己开店当老板(自建集群)。没有绝对优劣,只有适不适合自己的经营半径。

R+W>NR + W > N
读副本数 R 加上写副本数 W,大于总副本数 N 时,读写必然在某个副本上“碰头”,从而保证读到最新值。
  1. N(副本总数)同一份数据在集群里存几份,比如 3 副本。
    N=3N = 3
  2. R(读副本数)一次读请求至少等几个副本返回,例如 QUORUM 读 R=2。
    R=2R = 2
  3. W(写副本数)一次写请求至少几个副本确认,例如 QUORUM 写 W=2。
    W=2W = 2
  4. R+W>N读写覆盖集合必有交集,像开会时“至少有两个部门都到场的人”,保证消息不丢。
    2+2>32 + 2 > 3

选型优化成本

终于到了算总账的时刻。阿珍把一年的账单摊开:按需单价贵但灵活,预置单价便宜但怕闲置。核心判断指标还是那个“利用率”——只要利用率高到一定程度,包月就稳赚。以写请求为例,可以做一个简单的盈亏平衡估算:

优化路径可以总结为四步:第一步,分析访问模式,区分读多写少、高峰低谷;第二步,用 AWS Pricing Calculator 分别估算两种模式的月度成本;第三步,设置 CloudWatch 监控,盯着 ConsumedWriteCapacityUnits 和 ThrottledWriteEvents 这类指标;第四步,稳态高利用率场景采用预置加自动伸缩,波动大场景用按需,长期稳定还能考虑 AWS 的长期用量承诺折扣,最高可省下可观的比例。

阿珍最后把这笔账做成了一张表:不是越便宜的方案越好,而是最贴合客流曲线的方案最好。人少时别养闲厨子,人多时别让客人干等——这就是 DynamoDB 容量模式的经营哲学。

U盈亏=0.000651.25×10−6×3600×100%≈14.4%U_{\text{盈亏}} = \dfrac{0.00065}{1.25 \times 10^{-6} \times 3600} \times 100\% \approx 14.4\%
如果某个预置 WCU 的实际利用率持续高于约 14.4%,预置模式就比按需模式便宜;低于这个数,不如按需模式随用随付。
  1. 0.00065预置模式下 1 个 WCU 每小时的单价(美元),这是“包月厨师”的时薪。
    C预置/小时=0.00065 美元C_{\text{预置/小时}} = 0.00065\ \text{美元}
  2. 1.25×10⁻⁶按需模式下 1 个 WCU 的单价,即每百万个 1.25 美元折算到单个。
    1.25×10−6=1.251,000,0001.25 \times 10^{-6} = \dfrac{1.25}{1{,}000{,}000}
  3. 36001 小时有 3600 秒,100% 利用率下 1 个 WCU 每小时能处理 3600 个单位的写入。
    3600=60×603600 = 60 \times 60
  4. ≈14.4%把“年卡”和“单次”拉到平衡点,利用率超过它,包月更划算。
    14.4%≈0.000650.0045×100%14.4\% \approx \dfrac{0.00065}{0.0045} \times 100\%

AI 应用场景

电商大促订单表

阶段:数据存储与容量规划

解决的问题:传统预置模式下,大促流量无法预测,容量设低了会节流丢订单,设高了平时全是浪费。AI 推荐系统本身也对订单数据有突发的读写需求,容量模式选错会直接影响系统稳定性。采用按需模式后,读写请求单位实报实销,无惧秒杀尖峰。

具体案例:某电商平台每晚八点有整点秒杀,订单写入量在数秒内从 200 WCU 飙到 800 WCU。使用按需模式后,DynamoDB 自动扛住高峰,秒杀结束后账单又回到低谷,全程零节流。

IoT 设备心跳数据

阶段:数据采集与写入链路

解决的问题:数百万设备每小时上报一次心跳,写入量大且随时变化,固定预置容量极易浪费。按需模式配合设备 ID 作为分区键,让写入均匀分布到所有分区,同时免去容量预估的烦恼。

具体案例:共享单车平台每天收到数亿条定位心跳,用按需模式 + 设备 ID 分区键,写入成本与车辆活跃度严格挂钩,淡季成本自然下降。

游戏排行榜读多写少

阶段:在线推理结果存储与读取

解决的问题:游戏排行榜分数更新频繁但高峰明显,读请求远多于写请求。预置模式配合自动伸缩,以较低单价保障稳定的读吞吐;遇到赛季结算日,自动伸缩在几分钟内把读容量拉高。

具体案例:某手游赛季末排行榜页面 QPS 暴涨 5 倍,开启自动伸缩后,目标利用率 70%,系统按消耗量自动扩容,没有一次节流。

Python 演示

python44 行
import math def item_units(size_kb, mode):    """计算单条数据消耗的容量单位: 读按4KB, 写按1KB向上取整"""    if mode == 'read':        return math.ceil(size_kb / 4.0)    return math.ceil(size_kb / 1.0) def demand(hour):    """模拟一天客流: 晚上8点达到高峰, 清晨最低"""    peak = 0.5 + 0.5 * math.cos(2 * math.pi * (hour - 20) / 24)    writes_per_s = 20 + 80 * peak    reads_per_s = 4 * writes_per_s    return writes_per_s, reads_per_s def hourly_cost(prov_w, prov_r, writes_s, reads_s, size_kb):    """计算某小时两种模式各自的花费以及是否会节流"""    wcu = item_units(size_kb, 'write') * writes_s    rcu = item_units(size_kb, 'read') * reads_s    ondemand = wcu * 3600 * 1.25e-6 + rcu * 3600 * 0.25e-6    provisioned = prov_w * 0.00065 + prov_r * 0.00013    throttled_w = max(0, writes_s - prov_w / item_units(size_kb, 'write'))    throttled_r = max(0, reads_s - prov_r / item_units(size_kb, 'read'))    return ondemand, provisioned, throttled_w + throttled_r def main():    size_kb = 8    prov_w = 600    prov_r = 1600    total_on = 0.0    total_prov = 0.0    print("hour  on-demand  provisioned  throttled/s")    for hour in range(24):        ws, rs = demand(hour)        on, prov, thr = hourly_cost(prov_w, prov_r, ws, rs, size_kb)        total_on += on        total_prov += prov        if hour % 3 == 0:            print("{:2d}   {:8.4f}   {:8.4f}   {:6.1f}".format(hour, on, prov, thr))    print("24h total: on-demand ${:.2f}, provisioned ${:.2f}".format(total_on, total_prov))    print("提示: 把 demand() 改成尖峰流量, 就能看到按需模式的优势") if __name__ == '__main__':    main()
目的:用 24 小时模拟数据对比 DynamoDB 按需模式与预置模式的账单,并统计容量不足时被节流的请求量。
  1. return math.ceil(size_kb / 4.0)读取容量按 4KB 向上取整,数据越大消耗的 RCU 越多。
  2. return math.ceil(size_kb / 1.0)写入容量按 1KB 向上取整,写入比读取更“贵”,计价粒度更细。
  3. writes_per_s = 20 + 80 * peak用余弦函数模拟白天高峰与夜间低谷的流量曲线。
  4. wcu = item_units(size_kb, 'write') * writes_s每秒消耗的写容量单位 = 单条数据占用的 WCU × 每秒写入条数。
  5. ondemand = wcu * 3600 * 1.25e-6 + rcu * 3600 * 0.25e-6按需费用 = 每秒容量单位 × 3600 秒 × 每百万单位单价。
  6. provisioned = prov_w * 0.00065 + prov_r * 0.00013预置费用 = 预置 WCU × 小时单价 + 预置 RCU × 小时单价。
  7. throttled_w = max(0, writes_s - prov_w / item_units(size_kb, 'write'))每秒写入条数超过预置能承载的上限时,超出部分会被节流。
  8. if hour % 3 == 0:每 3 小时打印一次账单,方便观察早晚高峰的成本差异。

常见误区

误区我一直以为按需模式没有最低消费,不浪费容量,所以怎么算都比预置模式便宜。

正解按需模式虽然不浪费,但单价是预置模式的数倍。只要预置容量利用率持续高于约 14.4%,预置模式就明显更省钱。就像自助餐券:吃不到回本量就亏,吃够了就赚。省钱的关键不是“选哪个”,而是“你的利用率在哪条线之上”。

为何常见:人们只盯着“不浪费”这个优点,忽略了按需模式的高单价,属于典型的“省小钱花大钱”式误判。

误区我以为预置 100 个 WCU 就是最多支持 100 个请求同时进行,就像数据库连接池上限一样。

正解WCU 是“每秒吞吐量”单位,1 个 WCU 代表每秒写入 1KB 数据的能力,和并发数没有直接关系。一个 200KB 的批量写入请求可能瞬间消耗 200 个 WCU。类比:厨师的能力是用“每分钟炒几道菜”衡量的,而不是“锅里能站几个人”。

为何常见:新手容易把关系型数据库的“连接数”概念硬套到 NoSQL 的吞吐单位上。

误区我开了自动伸缩后就不管了,觉得任何流量高峰它都能瞬间扛住。

正解自动伸缩的评估周期通常是分钟级,扩容指令下发、生效都需要时间。秒级的流量尖峰到来时,伸缩还没跟上,请求已经被节流了。真正的秒杀防护要靠预留余量、突发容量或按需模式,自动伸缩只能应付“缓慢的潮汐”。

为何常见:“自动”两个字让人下意识联想到即时响应,忽略了监控采样和生效延迟的客观存在。

误区我以为只要数据小于 1MB,写入就只收固定 1 个单位的钱。

正解DynamoDB 按数据项大小精细计费:读按每 4KB 一个 RCU,写按每 1KB 一个 WCU,都向上取整。8KB 的写入要消耗 8 个 WCU,成本是 1KB 写入的 8 倍。优化项目大小,是成本优化里性价比最高的一步。

为何常见:习惯了 MySQL 按行数估算成本,忽略了 DynamoDB“按字节收费”的计费粒度。

误区我看两个都是键值存储,以为把连接串换一下就能互相迁移。

正解两者的数据模型、API、一致性机制、运维模式差异巨大。DynamoDB 是全托管服务,Cassandra 是自建集群;查询语言一个是 AWS 专有 API,一个是 CQL;强一致与可调一致的实现也不一样。迁移必须重写访问层并做充分的读写一致性测试,绝不可能“无缝替换”。

为何常见:只看到“键值对”这个表面相似性,忽略了存储引擎到运维体系的全栈差异。

面试题

Q1. DynamoDB 按需模式下,费用主要由什么决定?

单选题 · easy

  • A.固定包月费用
  • B.读写请求单位数← 正确答案
  • C.存储空间用量
  • D.最大并发连接

答案:B。按需模式没有最低消费,也没有预置容量,完全按实际消耗的读写请求单位数计费。存储空间是额外计费项,并发连接数在 DynamoDB 中并不是计费单位。就像大排档按“实际端出多少盘菜”收钱,而不是按店里能坐多少人收钱。

Q2. 1 个 WCU 最多支持每秒写入多少数据?

单选题 · easy

  • A.0.5 KB
  • B.1 KB← 正确答案
  • C.4 KB
  • D.8 KB

答案:B。写容量单位 WCU 以 1KB 为计价粒度,1 个 WCU 每秒最多写 1KB;4KB 是读容量单位 RCU 的粒度。写比读“贵”,是因为写入要做的处理更多,就像炒菜比端菜更费人工。

Q3. 下面哪个场景最适合使用按需容量模式?

单选题 · easy

  • A.流量长期稳定的订单表
  • B.有规律高峰的业务表
  • C.突发暴涨的服务日志表← 正确答案
  • D.固定报表周期的统计表

答案:C。按需模式的优势是无需预测容量、能承受突发尖峰,所以“突发暴涨的日志表”最合适。流量长期稳定、有规律高峰、固定周期报表都更适合预置模式搭配自动伸缩,因为它们的利用率可以预测,包月更省钱。

Q4. 预置模式下长期超出预留吞吐会发生什么?

单选题 · mid

  • A.请求自动排队等待处理
  • B.请求被节流直接拒绝← 正确答案
  • C.表自动切换为按需
  • D.数据自动迁移到新表

答案:B。DynamoDB 不会让请求无限排队,超过预置容量后会返回 ProvisionedThroughputExceededException,客户端需要指数退避重试。表不会自动切换模式,数据也不会迁移。就像厨房忙不过来时会礼貌地说“请您稍等”,而不是真的把客人晾在一边。

Q5. DynamoDB 自动伸缩策略的目标利用率默认约为多少?

单选题 · mid

  • A.30%
  • B.50%
  • C.70%← 正确答案
  • D.90%

答案:C。控制台下创建自动伸缩时,目标利用率默认是 70%,即给预置容量留出 30% 的缓冲余量,避免容量被完全打满后立刻触发节流。90% 太满,30% 又太浪费,70% 是稳定性和成本之间的折中。

Q6. 以下哪些做法能降低 DynamoDB 的使用成本?

多选题 · mid

  • A.缩小单条项目体积← 正确答案
  • B.使用高基数分区键← 正确答案
  • C.预留过高的预置容量
  • D.签订长期折扣合约← 正确答案

答案:ABD。缩小项目体积能减少每个请求消耗的 RCU/WCU;高基数分区键能避免热点分区造成的假性扩缩容;长期折扣合约(如 Savings Plans)能在稳定利用率的场景下直接降价。预留过高的预置容量只会增加闲置成本,反而更贵。

Q7. 某表总写吞吐需要 3000 WCU/s,至少需要几个分区来承载?

单选题 · hard

  • A.1 个
  • B.3 个← 正确答案
  • C.15 个
  • D.30 个

答案:B。每个分区最多支持 1000 WCU/s,3000 ÷ 1000 = 3 个分区。如果还要考虑读吞吐,则用每分区 3000 RCU 计算,取两者中的较大值。分区数不够会导致单分区超限,从而触发节流。

Q8. 关于 DynamoDB 突发容量,下列说法正确的有?

多选题 · hard

  • A.最多积攒五分钟未用容量← 正确答案
  • B.空闲容量自动永久保留
  • C.突发耗尽后仍可能被节流← 正确答案
  • D.只能用于读请求突发

答案:AC。突发容量最多积攒 300 秒(5 分钟)的未用容量,且用完即止,不会永久保留。它同时适用于读写,并不限定读请求。突发只是“短期借款”,长期超出预置容量依然会被节流,不能把突发当作永久的容量规划手段。

Q9. 与自建 Cassandra 相比,DynamoDB 的主要优势是?

单选题 · hard

  • A.完全免费开源
  • B.全托管免运维← 正确答案
  • C.多机房灵活部署
  • D.内置 SQL 查询

答案:B。DynamoDB 是 AWS 全托管服务,自动处理服务器、备份、扩缩容,这是它相对 Cassandra 最大的优势。Cassandra 才是开源免费、可多机房部署的自建方案。两者都不是 SQL 数据库,DynamoDB 使用自有 API。

Q10. 某表峰值需求 900 WCU/s 且波动剧烈,下列方案中合理的组合是?

多选题 · extreme

  • A.按需模式直接应对波动← 正确答案
  • B.预置满额配合自动伸缩← 正确答案
  • C.预置九成靠突发兜底
  • D.预置一半长期试重试

答案:AB。波动剧烈时,按需模式最省心,成本实时跟随流量;如果坚持用预置,则应该按峰值 900 配置并开启自动伸缩,确保有足够余量。预置九成靠突发只能撑 5 分钟,长期高峰必然节流;预置一半更是完全不够,重试会让系统雪上加霜。