使用 Amazon DynamoDB 对游戏玩家数据建模

模块 2:规划数据模型

构建实体关系图,预先规划访问模式

概述

数据建模是设计应用程序在特定数据库中的数据存储方式的过程。DynamoDB 等 NoSQL 数据库的数据建模与关系型数据库的建模不同。关系型数据库的特点是灵活性,非常适合分析型应用程序。在关系型数据建模中,您首先要处理实体 (entity) 关系。有了规范化的关系模型,就可以满足应用程序中需要的一切查询模式。

而 NoSQL(非关系型)数据库的特点是速度和规模,并非灵活性。关系型数据库的性能可能会随着容量扩展而降低,但 DynamoDB 等横向扩展的数据库在任何规模下都能保持一致的性能。一些 DynamoDB 用户的表大于 100 TB,而表的读写性能仍然保持与小于 1 GB 时的同等读写性能。

要充分利用 DynamoDB 等 NoSQL 数据库,就需要与使用典型关系型数据库时不一样的思维方式。在使用 DynamoDB 进行数据建模时,可采用以下最佳实践。

1.重点关注 access pattern(访问模式)
无论进行哪种类型的数据建模,首先都要建立实体关系图,描述应用程序中的不同对象(实体)以及它们之间的联系(实体之间的关系)。

在关系型数据库中,您要直接把实体存入表中,并使用外键指定关系。在定义了数据表之后,关系型数据库会支持灵活的查询语言,并以指定形式返回数据。

而在 DynamoDB 中,您要在对表建模之前就要考虑访问模式。NoSQL 数据库重点关注速度,而非灵活性。您首先要思考您会如何访问数据,然后根据访问数据的方式进行数据建模。

在设计 DynamoDB 表之前,清楚了解并记录应用程序中需要进行的数据读写。务必详尽无遗,并考虑到应用程序中的所有流程,因为您需要根据访问模式优化您的表。

2.优化对 DynamoDB 的请求数量
在记录下应用程序的访问模式需求之后,您就可以设计表了。设计表时,应尽量减少每个访问模式下对 DynamoDB 的请求数量。理想情况下,每个访问只需对 DynamoDB 发起一次请求,因为网络请求速度受限,会限制您在应用程序中的网络请求数量。

优化 DynamoDB 的请求数量之前,您需要理解一些核心概念:

3.不要伪造关系模型
刚开始使用 DynamoDB 的人通常会试图在非关系型的 DynamoDB 上实现关系模型。如果这样做,就享受不到 DynamoDB 的大部分优势了。

使用 DynamoDB 时最常见的反模式(对重复问题的无效响应)如下:

  • 规范化:在关系型数据库中,您要将数据规范化,以便减少数据冗余和占用的存储空间,然后要使用连接 (join) 来组合多个不同的表。然而,大规模数据表连接会导致速度慢、成本高。DynamoDB 不允许数据表连接,因为随着表数据增长,性能会变慢。
  • 每个表只包含一种数据:在 DynamoDB 表中,单个表通常会包含几种数据。在我们的示例中,单个表包含 User、Game 和 UserGameMapping 三个实体。而在关系型数据库中,这会被建模为三个不同的表。
  • 过多二级索引:人们通常会为需要的每个额外访问模式创建一个二级索引。而 DynamoDB 是无模式的,这也适用于索引。您可以利用属性的灵活性,将同一个二级索引用于一个表中的多种数据类型。这种方法称为索引重载

在以下步骤中,我们将构建实体关系图,预先规划访问模式。在使用 DynamoDB 时,必须完成这些步骤。然后,在后续模块中,我们要在表设计中实现这些访问模式。

 时长

20 分钟

 使用的服务

操作步骤

  • 在所有数据建模实践中,第一步都是构建示意图,展示应用程序中的实体以及实体之间的关系。

    我们的应用程序中有以下实体:

    • User
    • Game
    • UserGameMapping

    User 实体代表应用程序中的用户。一个用户可创建多个 Game 实体,而游戏创建者将决定游戏地图和每局游戏开始时间。因为一个用户可创建多个 Game 实体,所以用户游戏之间是一对多的关系。

    最终,一局游戏包含多个用户,而且随着时间推移,一个用户可以玩多局不同的游戏。因此,用户游戏之间也可以是多对多的关系。我们可以用 UserGameMapping 实体表示用户与游戏的关系。

    了解了这些实体和它们之间的关系,就能构建出以下实体关系图。

    Entity-relationship diagram
  • 需要为游戏用户创建用户画像。用户画像包括用户名、头像、游戏统计信息等数据,以及与用户相关的其他信息。用户登录时,游戏中会显示用户画像。其他用户可以查看某用户的画像,了解该用户的游戏统计信息和其他详细信息。

    在用户玩游戏时,游戏统计信息会更新。游戏统计信息反映当前用户的过往游戏局数、获胜局数和杀敌数。

    以上信息体现了三种访问模式:

    • 创建用户画像() 
    • 更新用户画像(
    • 获取用户画像(
  • 我们的示例游戏是一款大逃杀游戏。玩家可选择特定地图创建游戏,而其他玩家可加入游戏。加入游戏的玩家人数满 50 之后,游戏开始,且不再允许其他玩家加入。

    有些玩家在搜索要加入的游戏时,可能已经有了想玩的特定地图,而有些玩家可能不在乎地图,只想搜索在所有地图中可加入的游戏。

    根据此信息可得出以下七种访问模式:

    • 创建游戏(
    • 查找可加入的游戏(
    • 按地图查找可加入的游戏(
    • 查看游戏(
    • 查看游戏中的用户(
    • 为了某用户加入游戏(
    • 开始游戏(
  • 最后,我们来思考游戏中和游戏后的访问模式。

    在游戏期间,玩家要击败其他人,试图活到最后。这就需要应用程序跟踪每个玩家在游戏期间的杀敌数和存活时长。在游戏中存活到最后的三个玩家会分别获得金牌、银牌和铜牌。

    游戏结束之后,玩家可能会想要查看自己或其他玩家的过往游戏记录。

    根据此信息可得出三种访问模式:

    • 为用户更新游戏(
    • 更新游戏(
    • 为用户查找所有过往游戏记录(

总结

现在,我们已规划了游戏的所有访问模式。在后续模块中,我们要使用 DynamoDB 实现这些访问模式。

请注意,访问模式规划可能需要几次迭代更新。首先是应用程序所需访问模式的大致想法。然后映射表中的主键、二级索引和属性。接着回到访问模式规划,确保所有访问模式都得到实现。在确信认访问模式规划已完成后,进行后续操作步骤。

核心用途:用户画像和游戏