亚马逊AWS官方博客

乐信圣文游戏 DynamoDB 最佳实践:支撑千万日活游戏上线的数据库设计与运维策略

摘要:以乐信圣文旗下千万日活休闲游戏接入云端存档为例,分享 Amazon DynamoDB 实战:访问模式驱动的表结构设计、”预置预热→按需上线→稳定转预置”三阶段容量策略、Warm Throughput 分区预热、Service Quotas 规划及分层监控告警,兼顾高并发与成本优化。


一、前言

在移动游戏出海的浪潮中,如何让后端数据层既能扛住新版本上线时的突发流量,又能在业务稳定后保持成本可控,是每一个研发团队都要面对的课题。

乐信圣文是一家全球领先的移动出海游戏公司,秉承“把平凡无趣的时间,转化为有意义的时光”的使命,致力于“打造亿万人热爱、穿越时代、经久不衰的作品”。公司集游戏研发、运营、发行于一体,旗下有 Vita Mahjong、Tile Explorer、Amaze Go!、Mystery Town、Meowdoku等十余款爆款游戏作品。凭借品类深耕的业务战略,乐信圣文的版本成功率达到业界平均水平的 2 倍以上,多款产品广受好评并逐渐形成头部效应。截至目前,公司产品 MAU 已超过 3亿,累计用户超过 20 亿。

本文以乐信圣文旗下某热门游戏接入云端存档功能为例,分享团队在 Amazon DynamoDB 上围绕表结构设计、容量模式选择、分区预热以及监控告警的一整套实践经验,希望为面临类似场景的团队提供参考。

二、业务背景

乐信圣文旗下的游戏以休闲品类为主。这类游戏玩法轻量、用户规模大、生命周期长,商业化普遍以广告变现(IAA)为核心——用户留存与在线时长越高,广告变现的空间也越大。因此,如何延长用户生命周期、提升跨设备体验的连续性,是这类产品在精细化运营阶段共同关注的重点。

在早期用户体量有限时,玩家数据保存在本地即可满足需求;但随着用户规模持续增长,当 DAU 来到千万级,本地存储的局限开始显现:玩家一旦更换设备、重装游戏或清除数据,进度便无法找回,在如此庞大的用户基数上会直接造成可观的流失;同时,纯本地数据也难以支撑账号体系、跨端同步等更精细的运营手段。

在综合权衡用户体验、运营需求与技术成本后,团队经选型评估,决定为该热门游戏接入一套云端账号与存档服务。引入云端能力后,玩家可在任意设备上无缝找回并延续进度,显著改善体验连续性;账号与存档统一上云,也为后续的留存运营与数据分析打下基础。对于以广告变现为核心的休闲游戏而言,留存与生命周期的提升会直接转化为变现空间的增长。

三、业务层面的关键特征

在数据与访问层面,云端账号与存档服务则呈现出以下几个关键特征:

  • 访问模式简单:以按玩家 ID 查询单条记录为主,数据关系为一对一——一个用户仅有一条存档数据,写入即在该条数据上做更新。
  • 无复杂关系与聚合:不存在好友、公会等多对多关系,也没有排行榜需求。
  • 需要强一致性保障:存档场景可能存在”写后立即读”(read-after-write)的访问模式,且客户端的调用行为不完全可控,故默认采用强一致性读作为兜底策略。
  • 无事务、无 TTL 需求:当前业务不依赖 ACID 事务;存档为单条数据,不涉及过期删除。

四、为什么选择 DynamoDB

在决定将存档与账号服务上云后,团队对多种数据库方案进行选型评估后最终选择了 Amazon DynamoDB, 核心考量如下:

评估维度 DynamoDB 关系型数据库
(如 Aurora)
缓存方案
(如 ElastiCache)
访问模式适配度 天然适合按主键点查的 KV 模式 适合复杂查询与事务,本场景无此需求 适合高频读缓存,但不适合作持久存储
运维复杂度 全托管,无需管理实例与分片 需管理实例规格、读写分离、备份策略 需管理节点规模与集群拓扑
弹性能力 按需模式可自动伸缩,无需预判流量 需手动扩缩读副本或实例规格 支持增减节点,但需手动扩缩、难以瞬时弹性
延迟特征 个位数毫秒延迟,性能稳定 毫秒级,但复杂查询可能波动 亚毫秒级,但持久性不足
成本模型 按请求/预置计费,无闲置浪费 按实例小时计费,低谷期仍产生费用 按节点小时常驻计费,大规模场景成本偏高

结合本场景“一对一映射、按玩家 ID 点查、无复杂关联”的访问特征,DynamoDB 的 Key-Value 模型与全托管弹性能力恰好满足需求,同时避免了引入关系型数据库带来的额外运维开销。

五、表结构设计

DynamoDB 的表设计核心是“访问模式驱动”——先明确业务的查询方式,再据此决定主键与索引结构。结合前述业务特征(一对一关系、按玩家维度访问、无复杂聚合),团队整体仅使用三张表,分别承载账号、存档与登录态。

这三类数据的访问特征差异明显:账号与登录态体积小、访问频繁,每次鉴权和 token 刷新都需读取;存档则是整块游戏进度,数据较大但访问频率低。将它们分表存放,正是顺应了 DynamoDB 的计费模型——容量消耗与 item 大小直接挂钩,写入以 1 KB、读取以 4 KB 为单位向上取整计费,item 越大,单次读写消耗的 WCU/RCU 越多。若将这些数据混在同一张表甚至同一条记录中,每次高频的账号查询都会被迫连带读出较大的存档数据,白白抬高单次操作的 item size,造成容量浪费。分表之后,每条访问路径只触及自身真正需要的精简数据,这正是“只读写有用数据”这一最佳实践的体现,也使三类数据能各自按访问特征独立建模、独立扩容与监控。

[图1 三表结构与玩家流程]

在具体的主键与索引设计上,需要注意以下设计原则:

  • 读取均通过主键或 GSI 完成,避免使用 Scan。围绕核心访问模式建模,让每一类查询都能精确命中,从根本上保证读取效率与可预测的容量消耗。
  • 针对高频查询单独建立 GSI,并按需投影字段。将热点查询从主表卸载至独立索引,以隔离访问压力;同时,GSI 仅投影查询真正需要的字段而非全部属性,这是“只保留有用数据”原则在索引层面的延伸,可有效降低索引侧的存储与容量开销。
  • 提前规划索引键。GSI 的分区键与排序键一经创建便无法原地修改,调整只能新建 GSI 再删除旧索引;因此键结构应在设计阶段就结合未来的查询演进充分考虑,避免上线后被迫重建。

六、容量模式:上线用按需,稳定后转预置

DynamoDB 提供按需(On-Demand)与预置(Provisioned)两种容量模式,二者各有侧重:按需模式按实际请求计费、自动伸缩,适合流量不可预测的场景;预置模式按预设容量计费,配合 Auto Scaling 可在成本可控的前提下应对日常波动。针对新版本放量这一典型的“先不确定、后趋稳定”过程,团队并未在两种模式中二选一,而是沿放量的生命周期将容量策略划分为三个阶段——预置预热分区 → 按需平稳上线 → 稳定后转预置控成本,使每个阶段都匹配当时最主要的目标:防限流、抗突发、控成本。

[图2 三阶段容量策略时间线]

6.1 阶段一:上线前用预置模式预热分区

新表刚创建时底层分区数量有限。DynamoDB 的每个物理分区有固定上限——单分区最多支撑 1,000 WCU 和 3,000 RCU,存储上限为 10 GB,因此表的整体吞吐能力本质上由分区数量决定。而一张新建的按需模式表,初始预热吞吐仅为 12,000 RCU / 4,000 WCU。超出这一水位后,DynamoDB 虽会自动拆分分区、向上扩容,但分区分裂是异步过程、需要一定时间。在放量瞬间,如果突发流量快速越过初始水位,仅靠 burst capacity 与自适应容量兜底往往不够,容易触发限流。

团队的做法是在上线前主动“预热”分区:先以预置(Provisioned)模式创建或切换表,设置一个较高的 WCU/RCU。DynamoDB 会按目标吞吐重新规划分区——分区数量大致可按 WCU/1000 与 RCU/3000 推算并向上取整,预置容量越高,提前拆分出的分区就越多。待分区拆分完成后,再将表切回按需模式。切换后这些分区会被保留,表的预热吞吐也停留在此前建立的峰值水位,从而在放量时即可直接承接较高的瞬时流量。

需要注意分区预热应与实际吞吐目标相匹配,而非一味增加分区数量。由于 DynamoDB 会将预置容量在各分区间均摊,分区数量过多会导致单分区可分得的 WCU/RCU 被稀释;当某分区的容量无法支撑其实际访问量时,反而更易触发热分区问题。因此,预置容量应依据预估的峰值流量设定,避免为“预热”而盲目提升 WCU/RCU。

6.2 阶段二:上线时用按需模式应对突发

正式上线阶段切回按需模式。由于该能力随游戏新版本接入、并采用批量灰度放量,流量增长曲线难以精确预测:若沿用预置模式,可能会面临需要人工频繁上调容量或者为求稳妥而长期过量预置、造成浪费的情况。按需模式则将这部分弹性交由 DynamoDB 自动完成,团队在放量过程中无需盯着容量反复调整,可将精力集中于保障游戏整体稳定。

更重要的是,这一阶段并非从零冷启动。得益于阶段一已预热到位的分区,切换到按需模式后这些分区会被保留,放量初期的瞬时高峰可被直接承接,而无需从 12,000 RCU / 4,000 WCU 的初始水位再逐步爬升。与此同时,按需模式按请求计费的特性,也让这一阶段能够积累出清晰、真实的容量消耗曲线——这恰好成为下一阶段转预置、做精细化成本规划的数据基础。

6.3 阶段三:稳定后转预置模式优化成本

当用户基本完成版本迁移、流量趋于平稳后,团队通过 CloudWatch 观察一段时间内 WCU 与 RCU 的真实消耗水平,再将表切回预置模式并配置 Auto Scaling,既锁定成本,又保留应对日常波动的弹性。切换过程中沉淀了如下几条实践要点:

  • 初始预置值的设定。可参考 DynamoDB 控制台基于历史峰值给出的推荐值,估算方式为 初始值 = 峰值 / 目标利用率。例如观测到写入峰值约 5,000 WCU、目标利用率取 70%,则初始预置约 7,150 WCU,再以此为基准设置 Auto Scaling 的上下限。
  • Auto Scaling 的参数选择。建议将最大值设为历史峰值的 150%–200%(作为硬性上限),最小值设为低峰期平均消耗的 100%–120%,目标利用率则根据流量特征在 50%–80% 之间取值。目标利用率越高,闲置容量越少、越省成本,但也越逼近上限、容错空间越小;因此流量平稳时可取高值以提升性价比,突发明显时应取低值以预留缓冲。
  • GSI 需单独配置 Auto Scaling。GSI 的 Auto Scaling 需独立设置,不会随主表自动继承;GSI 写入被限流时会反压主表写入,必须为其预留充足的写容量。
  • 善用定时扩缩容。对于有明显规律的流量模式(如固定的每日高峰与低谷),可结合 Application Auto Scaling 的 cron 表达式定时调整最小吞吐量,在低谷时段主动下调下限,进一步节省成本。

6.4 模式切换的注意事项

  • 切换频率存在方向性限制。从预置模式切换至按需模式在 24 小时内最多可切换四次,而从按需模式切换至预置模式没有相关限制。
  • 切换至按需模式后,DynamoDB 以历史预置峰值为性能基线运行。从预置切换到按需的过程中,DynamoDB 会先按照此前预置的最大性能运行,并且存在 4,000 WCU / 12,000 RCU 的下限。因此当容量临时吃紧时,应急手段之一就是先拉高预置模式的上限,再执行切换。
  • Auto Scaling 的扩容存在天然延迟。它通常需连续观察到实际用量超过目标利用率约 2 分钟才会触发扩容,再叠加 CloudWatch 的指标采集延迟与容量扩展耗时,一次扩容实际完成往往需要 5–7 分钟;相比之下,缩容的触发则更为保守,以避免容量频繁抖动。正因如此,对突发流量敏感的业务而言,按需模式或较低的目标利用率往往是更稳妥的选择。

七、进阶:用 Warm Throughput 原生预热分区

前文“阶段一”采用的是一种“曲线救国”式的预热手法——先切到预置模式拉高 WCU/RCU 触发分区分裂,待分区到位后再切回按需。这套做法行之有效,但需要在两种容量模式间来回切换,操作链路较长。DynamoDB 还提供了Warm Throughput(预热吞吐量)功能,可以更直接地达成同样的目标。

什么是 Warm Throughput?预热吞吐量指的是一张表或 GSI在当前状态下能够瞬时承接的读写请求量。该指标对所有表和 GSI 默认可见、且不额外收费,其数值反映了表基于历史用量已经扩展到的水位,并会随着用量增长由 DynamoDB 自动上调。例如,一张新建的按需模式表,初始预热吞吐量即为 12,000 读单位/秒、4,000 写单位/秒——这正是前文反复提到的初始水位的由来。

对于产品发布、版本放量这类可预见的峰值事件,请求量可能陡增 10 倍、100 倍乃至更高,可以预先评估当前预热吞吐量是否足以支撑预期流量;若不足,则直接调高预热吞吐量即可,无需改动容量模式,也无需切换计费方式或写入任何数据。预热完成后,表便以这一更高的基线运行,从放量第一刻起就能稳定承接高并发请求。这一能力同时适用于新建及已有的单区域表、全局表与 GSI;对于全局表,所设置的预热值会自动应用到所有副本表。

以 AWS CLI 为例,可在一次 update-table 调用中同时为主表与指定 GSI 设定预热吞吐量:

aws dynamodb update-table \
    --table-name PlayerSaves \
    --warm-throughput ReadUnitsPerSecond=30000,WriteUnitsPerSecond=10000 \
    --global-secondary-index-updates \
        '[{"Update":{"IndexName":"PlayerSaves-GSI",
                     "WarmThroughput":{"ReadUnitsPerSecond":8000,"WriteUnitsPerSecond":4000}}}]' \
--region ap-northeast-1

预热为异步操作,表与索引的 Status 会先变为 UPDATING,完成后回到 ACTIVE;预热过程不会干扰表的正常读写。使用时需要注意以下几点:

  • 预热吞吐量只能上调、不可下调。因此应基于合理的峰值预估设定,而非盲目拉高。
  • 主动预热会产生费用。默认的预热吞吐量免费,但主动调高以预热表的请求会按相应规格计费,需纳入成本评估。
  • 预热不能消除热分区。预热只是抬高了表整体的瞬时吞吐基线,单分区 1,000 WCU / 3,000 RCU 的硬上限依然存在。若访问集中于少数分区键,即便远未触及表级预热值也可能被限流,因此仍需配合高基数分区键等设计来均匀分布流量。
  • 预热上限受配额约束。可预热的吞吐量上限等于该区域内账户的表级/索引级配额,这也呼应了下一节关于 Service Quotas 的规划——大规模预热前应先确认配额是否充足。
  • 对于本文的存档场景,若希望简化“阶段一”的操作,可直接为主表与各 GSI 设定一个贴合预估峰值的预热吞吐量,再切换至按需模式上线,从而省去预置/按需之间的反复切换,让分区预热这一步更加可控、可观测。

八、服务配额(Service Quotas)规划

在做高吞吐量规划时,除表级配置外,还需提前检查并提升账户级与表级的吞吐量配额,避免实际可用容量受限于配额上限。其中尤其要关注以下几项与吞吐量直接相关的关键配额,它们的默认值与限制级别如下表所示:

# 配额名称 默认值 级别 说明
1 Account-level read throughput limit (Provisioned mode) 80,000 RCU/Region 账户级 仅预置模式生效:单 Region 内账户下所有预置模式表 + GSI 已预置 RCU 的总和上限;按需模式的表不计入此配额
2 Account-level write throughput limit (Provisioned mode) 80,000 WCU/Region 账户级 仅预置模式生效:单 Region 内账户下所有预置模式表 + GSI 已预置 WCU 的总和上限;按需模式的表不计入此配额
3 Table-level read throughput limit 40,000/table 表级 单表(含其任一 GSI)的读上限——预置模式为最大可预置 RCU,按需模式为每秒可消耗的最大可消费读请求单位(RRU);该表及其 GSI 之和仍需低于账户级配额
4 Table-level write throughput limit 40,000/table 表级 单表(含其任一 GSI)的写上限——预置模式为最大可预置 WCU,按需模式为每秒可消耗的最大可消费写请求单位(WRU);该表及其 GSI 之和仍需低于账户级配额

注:上表 80,000 RCU/WCU 为账户级默认参考值(Global 默认);AWS 中国(北京 cn-north-1、宁夏 cn-northwest-1)等 Region 的默认配额可能不同,实际以各 Region 的 Service Quotas 控制台显示为准。

建议在上线前通过 Service Quotas 控制台一次性评估并申请到位,预留足够的提升处理时间。

九、监控告警体系

游戏平稳上线离不开完善的监控。团队的告警设计围绕三点展开:在指标选取上,既盯用户能直接感知的结果指标(如限流、延迟),也盯具备预警价值的领先指标(如容量水位);在告警编排上,按优先级分层,避免告警风暴;在处置上,为每一类告警预设“触发后如何响应”的动作,而不止于“如何发现”。

9.1 容量消耗告警

指标 建议阈值 告警条件 说明
ConsumedReadCapacityUnits ≥ 80% Provisioned 连续 5 分钟 读容量即将耗尽
ConsumedWriteCapacityUnits ≥ 80% Provisioned 连续 5 分钟 写容量即将耗尽

若使用按需模式,建议改为监控 ConsumedReadCapacityUnits / ConsumedWriteCapacityUnits 的绝对值变化趋势,并通过 metric math 将其换算为“距上次峰值”或“距配额上限”的比例,及时发现突发流量模式。

告警触发后,优先确认是否临近预置上限或账户配额,必要时上调 Auto Scaling 上限或临时切换至按需模式。

9.2 限流告警(Throttling)

指标 建议阈值 告警条件 说明
ReadThrottleEvents > 0 连续 1 分钟 读请求被限流
WriteThrottleEvents > 0 连续 1 分钟 写请求被限流
ThrottledRequests > 0 连续 1 分钟 所有被限流请求(支持按 API 维度拆分)

限流事件通常意味着容量不足或存在热分区(Hot Partition),需要立即关注。

告警触发后,先拉高预置上限或切换按需以快速止血,再结合 Contributor Insights 排查是否存在热点分区键。

9.3 系统与客户端错误告警

指标 建议阈值 告警条件 说明
SystemErrors > 0 连续 1 分钟 DynamoDB 服务端错误
UserErrors 异常突增 5 分钟内增长 > 50% 客户端请求错误激增

SystemErrors 为 DynamoDB 服务端错误(HTTP 5xx),通常是服务侧瞬时故障、多为可自愈,偶发无需干预,但持续出现或激增则需结合重试机制排查;UserErrors 为客户端请求错误(HTTP 4xx),突增的常见根因是 SDK 版本缺陷、请求参数校验失败或权限配置问题,应优先核对最近的客户端变更。

9.4 延迟告警

指标 建议阈值 告警条件 说明
SuccessfulRequestLatency (GetItem) P99 > 20ms 连续 5 分钟 单项读取延迟过高
SuccessfulRequestLatency (PutItem) P99 > 30ms 连续 5 分钟 单项写入延迟过高
SuccessfulRequestLatency (Query) P99 > 100ms 连续 5 分钟 查询延迟过高

延迟阈值应结合业务 SLA 调整,以上仅为通用建议值。若使用 BatchGetItem / BatchWriteItem、TransactWriteItems / TransactGetItems 等批量或事务操作,建议为其单独设置延迟告警,此类操作涉及多项读写,其延迟通常显著高于单 Item 操作。

9.5 GSI 告警

指标 建议阈值 说明
GSI ReadThrottleEvents > 0 GSI 读取被限流
GSI WriteThrottleEvents > 0 GSI 写入被限流(会反压主表写入)
OnlineIndexPercentageProgress > 30 分钟 GSI 回填进度异常

当 GSI 的写入容量不足而被限流时,反压会传导至主表,导致主表写入同样受阻。因此务必为每个 GSI 配置充足的写容量。

9.6 其他增强监控

  • CloudWatch Contributor Insights:开启后可直接定位被访问最多的 Top-N 分区键,是排查热分区的利器。
  • DynamoDB Streams:若开启了 Stream,建议为 Stream 的 IteratorAge 设置告警(如 > 60s),及时发现下游消费积压。
  • TTL 删除监控:若使用 TTL,可对 TimeToLiveDeletedItemCount 设置基线告警;突增可能意味着大量数据同时过期,骤降至 0 则可能意味着 TTL 配置被意外关闭。

十、最佳实践总结

回顾整个上线过程,可以提炼出以下几条核心经验:

  1. 以访问模式驱动表设计。应先厘清业务的查询方式,再据此确定主键与 GSI;对高频查询单独建立索引,且 GSI 仅投影必要字段,以控制存储与容量开销。
  2. 上线前预热分区,以按需模式承接突发。可通过预置模式提高 WCU/RCU,或直接使用原生的 Warm Throughput 设定预热基线来完成分区预热,二者都无需写入数据。无论采用哪种方式,分区数量都不宜过多,以免单分区容量不足而引发热分区。
  3. 稳定后转预置模式并借助 Auto Scaling 控制成本。应基于真实消耗数据判断切换时机,并为主表及每个 GSI 分别配置 Auto Scaling,必要时善用定时扩缩容。
  4. 提前规划 Service Quotas。账户级与表级的吞吐量配额均需提前评估并申请提升,避免上线时受配额限制。
  5. 建立分层监控告警。告警应覆盖容量、限流、错误、延迟、GSI 等各个维度,配合 Contributor Insights 快速定位热点,并为每类告警预设相应的响应动作。

回到业务本身,休闲游戏“以留存驱动广告变现”的商业逻辑,决定了数据层既要在新版本放量期扛住突发流量、保障玩家体验的连续性,又要在业务稳定后把成本压到合理区间。本文介绍的实践正是围绕这一目标展开:以访问模式驱动表设计,让数据结构精简高效;以“预热分区—按需上线—稳定转预置”的三阶段容量策略,让每个时期都匹配最关键的诉求;再以分层监控告警兜底,让风险在影响用户前被及时发现。三者结合,使云端账号与存档这类直接关乎留存的能力得以稳定、经济地长期运行。

对乐信圣文而言,正是在这套方法论的支撑下,旗下热门游戏顺利完成了云端账号与存档服务的接入——既平稳承接了新版本批量放量期的流量高峰,又在业务稳定后实现了成本优化,更沉淀出一套可复制到更多产品的数据层经验。我们也希望这些经验能为同样面临高并发、强留存诉求的游戏团队提供一份可参考的实践蓝本。

➡️ 下一步行动:

相关产品:

相关文章:

十一、参考资料

*前述特定亚马逊云科技生成式人工智能相关的服务目前在亚马逊云科技海外区域可用。亚马逊云科技中国区域相关云服务由西云数据和光环新网运营,具体信息以中国区域官网为准。

本篇作者

郭宁

乐信圣文游戏后端工程师,负责游戏业务后端研发与运维工作。

杨希婷

亚马逊云科技技术客户经理,主要支持游戏行业企业级客户出海业务的架构优化、成本管理、技术咨询等工作,目前专注于大数据方向的技术选型、方案落地和实践。

于泽沛

亚马逊云科技解决方案架构师,负责游戏行业客户的云计算解决方案咨询与设计,在 AI/ML、DevOps、游戏行业等领域拥有丰富经验。

吕琳

AWS数据库专家架构师,负责基于 AWS 的云计算方案的咨询与架构设计,同时致力于数据库和大数据方面的研究和推广。在加入AWS 之前曾在Oracle担任高级讲师并在Amazon担任高级DBA,在数据库设计运维调优、DR解决方案、大数据以及企业应用等方面有丰富的经验。

刘硕

亚马逊云科技客户解决方案经理,在亚马逊云科技主要支持游戏和零售等行业的用户。专注于促进亚马逊云科技用户解决方案落地,提升上云体验,帮助用户实现自身的业务价值。


AWS 架构师中心:云端创新的引领者

探索 AWS 架构师中心,获取经实战验证的最佳实践与架构指南,助您高效构建安全、可靠的云上应用