被 MySQL 的扩容问题折腾了一周后,我转向了 DynamoDB。坦白讲,一开始有点犹豫------NoSQL 嘛,总觉得没有 SQL 那么"正统"。但用了三个月,真的回不去了。
场景
用户行为日志系统:
- 写入:每秒几百到几千条
- 查询:按用户 ID 查最近操作(模式固定)
- 弹性:活动期间写入暴增 10 倍
MySQL 方案的问题:高峰期 CPU 拉满、需要手动扩容、为了抗峰值得开大实例但平时空跑。
30 秒理解 DynamoDB
一句话:Key-Value 数据库,按需付费,自动扩缩,个位数毫秒响应。
没有 Schema(除主键)、没有 JOIN、没有 GROUP BY。但写入极快,扩容无感,按量计费。
主键设计(最重要的部分)
sql
Partition Key: user_id
Sort Key: timestamp#uuid
- Partition Key 决定数据分布
- Sort Key 支持范围查询和排序
这两个字段定好了,其他字段随便加------DynamoDB 不需要 ALTER TABLE。
代码
写入
python
import boto3, time, uuid
table = boto3.resource('dynamodb').Table('user_actions')
table.put_item(Item={
'user_id': 'u_12345',
'sk': f'{int(time.time())}#{uuid.uuid4().hex[:8]}',
'action': 'click_button',
'page': '/dashboard',
'details': {'button_id': 'submit'}
})
查询
python
from boto3.dynamodb.conditions import Key
resp = table.query(
KeyConditionExpression=Key('user_id').eq('u_12345'),
ScanIndexDirection=False,
Limit=20
)
Query 走主键索引,几毫秒返回。
批量写入
python
with table.batch_writer() as batch:
for e in events:
batch.put_item(Item={...})
自动分批,自动重试限流。
四个坑
1. 热分区:所有写入打到同一个 Partition Key → 限流。解决:高频 Key 加随机后缀分片。
2. Scan 很贵:全表扫描按读取量计费。原则:查询只用 Query,永远不用 Scan。
3. GSI 最终一致:写入后立刻通过 GSI 查可能查不到。需要强一致的场景,用主表 Query。
4. Item 上限 400KB:大字段存 S3,DynamoDB 存引用地址。
三个月账单
| MySQL (RDS r5.large) | DynamoDB 按需 |
|---|---|
| ~$190/月 | ~$25/月 |
省了 87%。
什么时候别用
- 需要复杂 SQL(JOIN、子查询)→ 用 Aurora
- 查询模式不确定 → 关系数据库更灵活
- 单条记录 > 400KB → S3
一句话
写入多、查询模式固定、弹性要求高?DynamoDB 会让你少操很多心。
以上代码基于亚马逊云科技 DynamoDB + Python boto3 验证通过。DynamoDB 免费套餐每月 25GB 存储 + 足够的读写容量。