cswork / 系统设计

第 31 章 / 共 57 章 · 约 4 分钟

关键技术:DynamoDB 与 Cassandra

本页目录
  1. 1. 核心模型
  2. 2. 什么时候用
  3. 3. 什么时候不适合
  4. 4. 关键限制和数量级
  5. 5. 面试中常被追问的点
  6. 6. 和其他技术的取舍
  7. 7. 本站案例
  8. 章节测验

DynamoDB 和 Cassandra 都是按分区键水平扩展的键值 / 宽列存储:写入量几乎可以随节点线性增长,代价是放弃 JOIN 和灵活查询,表结构要围绕“会怎么读”来设计。两者放在一章讲,因为面试里的取舍几乎一样;区别在于一个是托管服务,一个是自己运维的无主集群。

1. 核心模型

  • 分区键决定数据放在哪里:对分区键做哈希,映射到某个分区或节点。同一分区键的数据放在一起。
  • 排序键决定分区内的顺序:DynamoDB 叫 sort key,Cassandra 叫 clustering key。“某个会话按时间倒序取 50 条”就是一个分区内的范围扫描,很快。
  • 一个查询一张表:没有 JOIN,要支持新的查询方式,通常是再建一个按另一种键组织的表或二级索引,把数据冗余写两份。

DynamoDB 特有的

  • 全托管,按读写容量(预置或按需)计费;单条 item 最大 400 KB。
  • 每个物理分区大约支持每秒 3000 个读容量单位和 1000 个写容量单位,热点分区会被限流(自适应容量能缓解,但不能根治)。
  • 默认最终一致读,可以选强一致读(只对主表,不对 GSI)。
  • 条件写(ConditionExpression)做乐观锁;事务 API 一次最多 100 个 item。
  • GSI(全局二级索引)是异步维护的,有延迟;Streams 提供 24 小时内的变更流;TTL 自动删除过期 item。

Cassandra 特有的

  • 无主(leaderless):一致性哈希环加虚拟节点,每份数据复制到 N 个节点(常见 RF=3)。
  • 每次读写可以选一致性级别:ONE、QUORUM、LOCAL_QUORUM、ALL。读写都用 QUORUM 时 R + W > N,能读到最近一次已确认的写入。
  • 存储引擎是 LSM 树:先写内存表和提交日志,再刷成 SSTable,后台合并(compaction),所以写入很快。
  • 冲突按时间戳“后写者胜”;删除写的是墓碑(tombstone),大量删除会拖慢读取。
  • 轻量事务(IF NOT EXISTS)基于 Paxos,比普通写入慢好几倍,只在必要时用。

2. 什么时候用

  • 写多、按 key 读:聊天消息、操作日志、IoT 时序、位置轨迹、活动流。
  • 规模大且可预测:数据量几十 TB 以上、吞吐要随业务线性扩展。
  • 需要稳定的低延迟键值访问:会话、购物车、用户配置(DynamoDB 尤其省心)。
  • 多数据中心写入:Cassandra 的多 DC 复制配合 LOCAL_QUORUM,每个机房本地读写。

3. 什么时候不适合

  • 查询方式还不确定:临时查询、多维筛选、聚合报表都很难做,PostgreSQL 更合适。
  • 跨多条记录的强一致事务:扣库存同时写订单、转账两边同时改,关系数据库更自然;DynamoDB 事务有数量和成本限制,Cassandra 基本没有。
  • 频繁更新同一行或大量删除:Cassandra 的墓碑和 LWW 让这类负载很难受。
  • 小规模:几十 GB 的数据,用宽列存储只会增加建模成本。

4. 关键限制和数量级

维度DynamoDBCassandra
单条大小item 最大 400 KB单个值建议远小于 1 MB
分区大小单个分区键下数据无硬上限,但吞吐受单分区限制单个分区建议控制在 100 MB 以内,太大读写和修复都慢
单分区吞吐约 3000 RCU / 1000 WCU 每秒取决于节点,热分区会压垮持有它的几个副本
一致性默认最终一致,可选强一致读每次请求可调,QUORUM 读写可读到最新确认写入
扩容自动拆分区加节点后数据在环上重新分布

5. 面试中常被追问的点

  • 分区键怎么选? 让访问均匀分布,同时让最常见的查询只打到一个分区。聊天消息用 (conversation_id, month) 做分区键,既保证一个会话的消息在一起,又限制单个分区的大小。
  • 热点分区怎么办? 写入时给 key 加后缀(item#0..item#9)打散,读时并发查 10 个再合并;或者在前面加缓存。
  • 需要按另一个字段查? DynamoDB 建 GSI(接受最终一致);Cassandra 一般再建一张反向表,由应用同时写两张表,或者用 CDC 同步。
  • 计数器怎么做? Cassandra 有 counter 类型但不是幂等的,重试会多加;DynamoDB 用 UpdateItem ADD 原子加。要求精确时,按事件写明细,再异步聚合。
  • 怎么实现乐观锁? DynamoDB 用版本号加 ConditionExpression;Cassandra 用轻量事务 IF version = ?,注意性能代价。

6. 和其他技术的取舍

选项适合代价
DynamoDB托管、免运维、键值访问访问模式要提前设计;云厂商锁定;热点分区限流
Cassandra / ScyllaDB自己掌控的超大写入量、多数据中心运维重,一致性和墓碑需要经验
PostgreSQL事务、约束、灵活查询写入受单主限制
Bigtable / HBase超大有序宽表、扫描生态和运维各有门槛

7. 本站案例

章节测验

5 道选择题
  1. 聊天消息存在 Cassandra 里,按 conversation_id 做分区键。一个超大群聊几年下来分区越来越大,该怎么改?
  2. Cassandra 集群 RF=3,怎样配置读写一致性,才能保证读到最近一次已确认的写入?
  3. DynamoDB 表按 product_id 分区,某个爆款商品的写入被持续限流。最合适的处理是?
  4. 下面哪个场景最适合用 DynamoDB 或 Cassandra?
  5. DynamoDB 的全局二级索引(GSI)有什么需要在设计里说明的特性?

章节讨论

正在加载讨论…