从 MySQL 到 DynamoDB:一次真实项目的数据库迁移实践与性能对比

项目背景

在一个用户行为分析系统中,原有架构使用 RDS MySQL (db.r5.large) 存储操作日志。随着业务增长,写入量从每秒几十条增加到每秒数千条,MySQL 方案暴露出几个问题:

  1. 高峰期 CPU 持续 90%+,影响查询响应
  2. 扩容需要停机或切换,无法平滑应对突发流量
  3. 为抗住峰值需要预留大实例,平时利用率不到 10%

基于这些问题,我们评估了亚马逊云科技 DynamoDB 作为替代方案。

DynamoDB 核心特性

DynamoDB 是一个全托管的 Serverless NoSQL 数据库:

  • 自动扩缩容:无需手动调整读写容量
  • 按需计费(On-Demand 模式):按实际读写请求计费
  • 个位数毫秒延迟:无论表的大小如何
  • 高可用:数据自动复制到三个可用区

表设计

操作日志的数据模型:

表名: user_actions
Partition Key: user_id (String) — 按用户分区
Sort Key: sk (String) — timestamp#action_id,按时间排序

设计考虑

  1. Partition Key 选择高基数字段(user_id),避免热分区
  2. Sort Key 使用时间戳前缀,支持按时间范围查询
  3. 追加 uuid 后缀防止同一毫秒的写入冲突

代码实现

写入

import boto3, time, uuid

table = boto3.resource('dynamodb', region_name='ap-northeast-1').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', 'form': 'login'}
})

查询

from boto3.dynamodb.conditions import Key

response = table.query(
    KeyConditionExpression=Key('user_id').eq('u_12345'),
    ScanIndexDirection=False,
    Limit=20
)

批量写入

with table.batch_writer() as batch:
    for event in events:
        batch.put_item(Item={
            'user_id': event['user_id'],
            'sk': f'{event["ts"]}#{uuid.uuid4().hex[:8]}',
            'action': event['action'],
            'page': event['page']
        })

batch_writer 自动分批(每批 25 条),自动处理限流重试。

迁移过程中的问题

热分区

部分系统账号(如 adminsystem)的写入量远超普通用户,导致对应分区被限流。

解决方案:对高频 Partition Key 添加随机后缀进行分片。

Scan 陷阱

初期有个报表查询用了 table.scan(),扫描 200GB 数据耗时 3 分钟。改成 GSI + Query 后降到毫秒级。

生产环境应避免使用 Scan,所有查询走 Query 或 GSI。

GSI 一致性

Global Secondary Index 是异步复制的,存在毫秒级延迟。写入后立刻通过 GSI 查询可能读不到最新数据。需要强一致性的场景使用主表 Query。

迁移前后对比

指标 MySQL (RDS r5.large) DynamoDB (On-Demand)
月成本 ~$190 ~$25
写入延迟 (P99) 15ms 5ms
扩容方式 手动/预定义 全自动
运维工作量 备份/监控/升级 接近零
查询灵活性 SQL 支持所有查询 只支持主键/索引查询

适用性分析

DynamoDB 适合:

  • 写入密集 + 读取模式固定 的场景
  • 需要自动弹性扩缩的应用
  • Key-Value 或宽列数据模型

关系数据库更适合:

  • 查询模式复杂多变(JOIN、聚合、子查询)
  • 强数据关联(多对多关系)
  • 需要事务一致性保障的金融场景

小结

这次迁移的核心收益是成本降低 87% 和运维工作量接近归零。DynamoDB 的按需计费模式在写入量波动大的场景下有明显的成本优势。

局限性方面,查询灵活性不如 SQL,表设计需要提前考虑好访问模式。但对于明确的 Key-Value 查询场景,DynamoDB 的性能和成本表现确实很好。

以上代码基于亚马逊云科技 DynamoDB + Python boto3 验证通过。

posted @ 2026-03-18 07:04  亚马逊云开发者  阅读(0)  评论(0)    收藏  举报