非关系排行榜参考体系结构

用于小规模部署的简单排行榜

S简单排行榜的外观

体系结构关系图

S使用非关系数据库、适合小规模部署的简单排行榜

实现详细信息

在此包含源代码的完整教程中,您可以学到如何实现一个排行榜,该排行榜将 Azure Redis 缓存与另一个数据库配合使用,以提高数据吞吐量并减少数据库负载。

它利用了使用 Azure Redis 缓存作为持久性数据库后端缓存层的缓存端模式。 每次进行写操作时,都会将数据写入持久性数据库和 Azure Redis 缓存。 每次读取时,首先从缓存读取数据,如果未命中(数据因在特定时间后到期而不再存在于缓存中),则从持久性数据库读取数据,然后立即将其写入缓存。 如果缓存命中,则从缓存读取数据。

此示例使用实体框架(一个 .NET 抽象层)对数据对象之间的关系进行建模和表示。 简而言之,从编程模型角度看,使用实体框架时,您所做的是获取一组对象和设置这些对象的属性,然后实体框架会将所有操作都映射到 SQL 操作。

分步说明如下:

  1. 设备客户端连接到 Azure Web 应用(Web 服务,如上面的体系结构图所示),以上传新的玩家记录。 或者,您也可以将 Web 服务替换为 Azure Functions 等(每个函数执行特定的任务),或将负载均衡器替换为虚拟机。
  2. Azure Web 应用接收上传新记录的操作,并按照缓存端模式,先将其写入持久性数据库,在本例中为 Azure SQL 数据库
  3. 之后,继续按照缓存端模式,将同一记录保存到 Azure Redis 缓存数据库。
  4. 另一位玩家想要查看特定的排行榜,因此他可以连接到 Azure Web 应用(Web 服务)。
  5. Azure Web 应用接收从特定排行榜检索记录的操作。 它首先尝试从 Azure Redis 缓存进行读取。 如果在缓存中找到记录(命中),则直接将信息返回给设备客户端。
  6. 如果尝试从 Azure Redis 缓存读取记录的尝试未命中(数据因在特定时间后到期而不再存在于缓存中),则 Azure Web 应用将从持久性数据库读取记录,在本例中为 Azure SQL 数据库
  7. 然后,将从持久性数据库检索到的记录保存到 Azure Redis 缓存,最后发送到设备客户端。

备选方案

除了 Azure SQL 数据库之外,您也可以使用其他数据库,例如 Azure Database for MySQL

用于大规模部署的高级排行榜

体系结构关系图

非关系数据库排行榜用例

体系结构服务

此实现使用 Azure 函数而不是 Azure Cosmos DB SDK 写入数据。 如果您需要更精细的控制和调试,可以利用应用程序服务和更改处理器 SDK

体系结构注意事项

在为游戏设计排行榜时,有一些设计注意事项和选择。

主集合、分区和分区键

在继续介绍之前,有必要解释一下 Azure Cosmos DB 的一些基础方面。

分区是 Azure Cosmos DB 用于缩放数据库中各个容器的技术。 容器中的项目分为不同的子集,称为逻辑分区。

逻辑分区是基于与每个项目关联的分区键属性的值创建的,它们是容器中项目的不同子集。

逻辑分区中的项目由逻辑分区中所有项目共享的分区键值标识。 例如,假设有一个存放文档的容器,每个文档都有一个 UserID 属性。 如果 UserID 用作容器中项目的分区键,并且有 1000 个唯一的 UserID 值,则将为容器创建 1000 个逻辑分区。

容器中的每个项目都有一个分区键(用于确定项目的逻辑分区),并且每个项目还有一个项目 ID(在逻辑分区中是唯一的)。 项目的索引唯一地标识此项目,它通过组合分区键和项目 ID 形成。

定义分区键时,需要考虑三个关键事项:

  1. 虽然每个集合可以有大量分区键,但每个分区键有 10GB 限制。
  2. 无法更新分区键。 如果创建了分区键 A_B_C,以后无法将其更新为 A_B_C_D。 但是,可以创建新键并迁移数据。
  3. 目标是将工作负载平均分配到所有分区,以避免出现热点

有关如何为排行榜选择分区键的所有详细信息,请参阅选择分区键

此排行榜参考体系结构的实现将利用全球排行榜常规集合(也就是存储所有条目的主集合)和每个值组合的分区键

在此用例中,将根据两个变量对玩家的得分进行排名:平台和关卡,其中使用的分区键为 level_system

举一个具体示例,如果在 Xbox 和 PlayStation 平台上都发布了使用此参考体系结构和实现的游戏,并且此游戏只有两个关卡(1 和 2),那么最终将在 Azure Cosmos DB 中生成以下集合和分区:

  • 主集合
  • 分区 1 (all_all)
  • 分区 2 (xbox_all)
  • 分区 3 (ps4_all)
  • 分区 4 (all_level1)
  • 分区 5 (all_level2)
  • 分区 6 (xbox_level1)
  • 分区 7 (ps4_level1)
  • 分区 8 (xbox_level2)
  • 分区 9 (ps4_level2)

架构为:

{
    "id": "1",
    "platform": "Xbox Live",
    "level": 3,
    "character": "Damian",
    "name": "Brian",  //platform gamertag
    "xp": 12345, // stat 1
    "quests": 12 //stat 2
}

仅出于澄清目的,我们使用赛车游戏中的 3 个变量来演示在更复杂的场景中会发生什么情况:关卡(Laguna Seca 和 Monza)、选择(快车组和慢车组)和统计信息(最快圈速和捡拾道具数)。 使用的分区键结构为 level_choice_stat,当用户上传记录时,将生成以下组合:

  • 主集合
  • 分区 1 (lagunaseca_fastclass_fastestlap) [000]
  • 分区 2 (lagunaseca_fastclass_powerupspicked) [001]
  • 分区 3 (lagunaseca_slowclass_fastestlap) [010]
  • 分区 4 (lagunaseca_slowclass_powerupspicked) [011]
  • 分区 5 (monza_fastclass_fastestlap) [100]
  • 分区 6 (monza_fastclass_powerupspicked) [101]
  • 分区 7 (monza_slowclass_fastestlap) [110]
  • 分区 8 (monza_slowclass_powerupspicked) [111]

在这种情况下,如果第一位玩家使用属于快车组(选择)的汽车在 Monza(关卡)赛道上行驶,则存储在 Azure Cosmos DB 中的信息将如下所示:

全球排行榜集合 (leaderboards_all_data) { userID: "XYZ", stat: "fastestlap", choice: "fastclass", level: "monza", value: "123" } { userID: "XYZ", stat: "powerupspicked", choice: "fastclass", level: "monza", value: "1" }
分区 5 (monza_fastclass_fastestlap) { userID: "XYZ", stat: "fastestlap", choice: "fastclass", level: "monza", value: "123" }
分区 6 (monza_fastclass_powerupspicked) { userID: "XYZ", stat: "powerupspicked", choice: "fastclass", level: "monza", value: "1" }

级联写入模式

由于必须将信息写入主集合和至少一个或多个子表,尤其是在有相关变量的情况下(例如:iOS、Android 和移动设备, 其中移动设备是一个筛选条件,将显示来自 iOS 及 Android 用户的记录),最佳实践是只执行单个写入操作,而将可能受涓流效应影响的工作交给 Azure Cosmos DB 更改源完成,以避免实际仅完成一次写入时可能导致的不一致。

分区键更新

如前所述,您无法更新现有分区键,但可以添加新分区键。

继续 twp 变量示例,假设您想再添加一个,以便可以根据用户选择的游戏难度设置(简单、中等、困难)拆分数据。 为此,您需要从旧分区键 level_system 升级为 level_system_difficulty。 为了绕过无法更新现有分区键的限制,可以使用迁移工具执行下述步骤:

  1. 使用更改源排出整个集合。
  2. 使用其他分区键重新引入数据。

每秒 Azure Cosmos DB 请求单位

请查看一般指南文档,了解 Azure Cosmos DB 集合如何计费、如何跟踪请求单位数以及请求它们的经验。

部署模板

请查看一般指南文档,其中有一篇文章概述了 Azure 服务的命名规则和限制。

优化注意事项

关于优化 Cosmos DB 成本,可以查看以下有用资源:

其他潜在功能

添加对推送通知的支持

根据玩家使用的平台,您可能希望实现下述功能:例如,当玩家好友的分数超过此玩家时向其发送通知。可以利用 Azure Cosmos DB 更改源Azure 通知中心服务实现此类功能。

推送通知支持体系结构

其他资源和示例

通过 MongoDB API 访问 Functions 和 Cosmos DB

使用 Mongo API 设置托管在 Azure Functions 上并由 Azure Cosmos DB 提供支持的游戏排行榜 API,以通过 HTTP/HTTPS 方法/操作存储游戏排行榜(分数)和公开排行榜分数。 在您的游戏中使用此 API 服务发布新分数、获取最高分、找出最新分数等等。

定价

如果您没有 Azure 订阅,可以创建免费帐户,开始使用 12 个月的免费服务。 除非您超出这些服务的使用限制,否则无需为 Azure 免费帐户中包含的这些免费服务付费。 了解如何通过 Azure 门户使用情况文件查看服务使用情况。

您需要承担运行这些参考体系结构时使用的 Azure 服务的费用,总金额取决于将通过分析管道运行的事件数。 请参阅参考体系结构中使用的每项服务的定价网页:

您还可以使用 Azure 定价计算器,以配置和估算您计划使用的 Azure 服务的成本。