MongoDB迁移到Cosmos DB以支持数百万用户 - Saket


Glance 游戏中心是 Glance 应用程序中的一个部分 : 上百款游戏的目的地。任何想要快速娱乐的人都可以在这里玩游戏。它涵盖了各种类型的游戏,如益智、赛车、冒险、策略等。这些游戏通常是基于 HTML5 的简单游戏,无需安装即可玩。玩家还可以参加正在进行的锦标赛并与其他玩家竞争;最终赢得奖品等。
 
问题陈述
我们有休闲摹针对比赛都跑,每天增加用户参与度和奖励他们根据他们的队伍我们的锁屏上埃姆斯。每个游戏及其相应的锦标赛都有一个排行榜,其数据当前存储在自托管的 Mongo DB 中。排行榜显示顶级玩家以及他们的分数、您当前的分数和您的排名。这是在玩家之间创造竞争的一个特别重要的屏幕。手头的问题是将我们的排行榜扩大 100 倍,使我们能够运行多个并发锦标赛,目前这些锦标赛受到单个节点非分片 MongoDB 的限制。
 
规模
每天有数百万用户访问游戏中心。排行榜 MongoDB 目前拥有超过 3 个集合的超过 1000 万个文档。后端服务接收大约 500 QPS 的流量,进而以大约 1000 QPS 的速度访问数据库,包括读取和写入。
考虑的解决方案

  • 将当前 MongoDB 横向扩展为多节点分片集群
  • 使用完全托管的云数据库

我们继续使用后者并使用Cosmos DB,原因如下:
  • 更易于扩展、维护和支持
  • 在我们的预算内没有重大的成本差异
  • 无停机时间且易于迁移
  • 不再需要手动进行每日数据备份转储
  • 团队熟悉 Azure 生态系统,在相同的基础上再添加一个更容易

 
执行迁移
首先介绍一下 COSMOS DB
Cosmos DB 为我们提供了多个接口和 API,可以轻松地从其他数据库(如 MySQL、Cassandra、MongoDB 等)迁移……在我们的例子中,我们选择了 Azure Cosmos DB 的 API for MongoDB v4,我们只需要替换代码中的 DB 连接字符串,我们很高兴去。
所有数据库操作的成本由 Azure Cosmos DB 规范化,并以请求单位(或简称 RU)表示。请求单位是一种性能货币,它抽象了执行 Azure Cosmos DB 支持的数据库操作所需的 CPU、IOPS 和内存等系统资源。
核心 API 和查询
  • 获取比赛的用户分数
  • 获取用户在锦标赛中的排名
  • 获得锦标赛的前 N ​​位领袖
  • 更新锦标赛的用户分数

 
在COSMOS中选择索引和分区键
老MongoDB的数据模型具有收藏tournamentHighScore包含字段ID,用户id,tournamentId,高分和一些更多的元数据。
新的 Cosmos DB 包含与上述相同的字段,以及一个额外的合成分区键,我们将其构建为锦标赛 ID_userId以优化点读取/更新以及在逻辑/物理分区之间均匀分布数据以避免热分区。
以下索引已添加到 Cosmos DB 的集合中:
  1. 锦标赛ID(单键索引)
  2. highScore(单键索引)
  3. 锦标赛ID:1,高分:-1(复合指数)

添加 1 和 2 以优化排名查询,该查询计算得分大于您的用户数量,添加 3 以有效获得锦标赛的前 N ​​位领先者。请注意,与 MongoDB 不同的是,复合索引仅用于对结果进行排序的查询,对于其他多个字段的查询,单键索引工作得很好。
 
零宕机迁移
  • 所有的读取和写入都是通过 MongoDB 进行的。
  • 我们与 Cosmos DB 建立新连接,并开始对两个数据库的双重写入,同时仍从 MongoDB 读取。
  • 现在,我们需要将数据从 MongoDB 迁移到 Cosmos DB 以完全复制数据。

使用 Azure数据库迁移服务是一种直接且可靠的数据传输方式,但它不支持我们的 MongoDB 版本。
作为上述解决方案,我们在排行榜服务中公开了一个端点,该端点从 MongoDB 批量读取数据并将其写入 Cosmos DB。两个数据库的主键都在代码中生成,从而防止对 Cosmos DB 的任何重复写入。此端点在迁移结束后被删除
  • 数据迁移后,我们将读取从 MongoDB 切换到 Cosmos DB,同时仍然写入前者进行备份。
  • 经过进一步监控,我们停止了对 MongoDB 的所有写入,并丢弃了旧数据库。