amazon-web-services - 用于查询多值属性的 DynamoDB 表/索引架构设计
问题描述
我正在构建一个最终将为大量(数百万)用户提供服务的 DynamoDB 应用程序。目前,该应用的项目架构很简单:
{
userId: "08074c7e0c0a4453b3c723685021d0b6", // partition key
email: "foo@foo.com",
... other attributes ...
}
当新用户注册时,或者如果用户想通过电子邮件地址查找其他用户,我们将需要查找用户 byemail
而不是 by userId
。使用当前模式很容易:只需使用全局二级索引email
作为分区键。
但是我们希望为每个用户启用多个电子邮件地址,并且 DynamoDBQuery
操作不支持List
-typed KeyConditionExpression
。因此,我正在权衡几个选项,以避免Scan
每次用户注册或希望通过电子邮件地址找到另一个用户时进行昂贵的操作。
以下是我计划更改的内容,以便为每个用户启用额外的电子邮件。这是一个好方法吗?有更好的选择吗?
- 添加一个排序键列(例如
itemTypeAndIndex
)以允许每个userId
.
{
userId: "08074c7e0c0a4453b3c723685021d0b6", // partition key
itemTypeAndIndex: "main", // sort key
email: "foo@foo.com",
... other attributes ...
}
- 如果用户添加了第二封、第三封等电子邮件,则为每封电子邮件添加一个新项目,如下所示:
{
userId: "08074c7e0c0a4453b3c723685021d0b6", // partition key
itemTypeAndIndex: "Email-2", // sort key
email: "bar@bar.com"
// no more attributes
}
相同的全局二级索引(
email
作为分区键)仍可用于查找主要和非主要电子邮件地址。如果用户想要更改他们的主要电子邮件地址,我们将交换
email
“主要”和“非主要”项目中的值。(现在 DynamoDB 支持事务,这样做会比以前更安全!)如果我们需要删除一个用户,我们必须删除该用户的所有项目
userId
。如果我们需要合并两个用户,那么我们必须为此合并所有项目userId
。相同的方法(具有相同
userId
但不同排序键的新项目)可用于其他需要Query
-able的 1-user-has-many-values 数据
这是一个好方法吗?有没有更好的办法?
解决方案
Justin,对于搜索属性,我强烈建议不要使用 DynamoDB。我不是说,你不能做到这一点。但是,我看到一些问题最终会出现在你的道路上,如果你会去这个根。
- 在 email-id 上使用排序键将导致为同一用户创建重复记录,即如果用户注册了 5 封电子邮件,这意味着您的表中有 5 条记录具有相同的架构和属性,但 email-id 属性除外。
- 如果将来出现新的用例,现在您还想根据其他属性(例如手机号码,假设用户可能有多个手机号码)搜索用户怎么办?
- DynamoDB 对您可以为表创建的二级索引数量有硬性限制,即 5。
因此,随着搜索条件用例的增加,该解决方案很容易成为您系统的瓶颈。因此,您的系统可能无法很好地扩展。
据我所知,我可以建议您可以根据您的要求/预算选择一些选项,以使用数据库组合来解决此问题。
Option 1.
DynamoDB 作为主存储,AWS Elasticsearch 作为二级存储 [首选]
- 当用户注册时,将用户记录存储在 DynamoDB 表(我们称之为UserTable)中。
- 在UserTable表上启用 DynamoDB 表流。
- 构建一个从表的流中读取数据并将记录保存在 AWS Elasticsearch 中的 AWS Lambda 函数。
现在在您的应用程序中,使用 DynamoDB 从 id 获取用户记录。对于所有其他搜索条件(如搜索 emailId、电话号码、邮政编码、位置等),从 AWS Elasticsearch 获取记录。AWS Elasticsearch 默认为您记录的所有属性编制索引,因此您可以在延迟毫秒内搜索任何字段。
Option 2.
使用 AWS Aurora [不太喜欢的解决方案]
如果您的应用程序具有数据相关的关系用例,您可以考虑使用此选项。顺便说一句,Aurora 是一个 SQL 数据库。由于这是一个关系存储,您可以选择在多个表中组织记录并根据这些表的主键连接它们。
我将建议第一个选项为:
- DynamoDB 将为您的应用程序提供持久、高可用性、低延迟的主存储。
- AWS Elasticsearch 将充当二级存储,它也是持久、可扩展和低延迟的存储。
- 使用 AWS Elasticsearch,您可以在您的表上运行任何搜索查询。您还可以对数据进行分析。Kibana UI是开箱即用的,您可以使用它在仪表板上绘制分析数据,例如(用户增长趋势如何,有多少用户属于特定位置,基于城市/州/国家的用户分布等)
- 使用 DynamoDB 流和 AWS Lambda,您将近乎实时地同步这两个数据库 [在几毫秒内]
- 您的应用程序将是可扩展的,并且可以进一步增强搜索功能以对多级属性进行过滤。[一个这样的例子:搜索属于给定城市的所有用户]
话虽如此,现在我将由您决定。
推荐阅读
- reactjs - 打字稿通知编译器正在使用哪种联合类型
- boolean - 是否有在 Google Data Studio CASE 语句中评估布尔变量的解决方法?
- c# - 无法加载文件或程序集'System.Threading.Tasks.Dataflow,版本 = 4.6.3.0
- google-chrome - Google Chrome - 重新加载时检查 CSS 网格?
- javascript - 如何访问变量中元素的类
- python - python pcolormesh 不同背风角沙丘上流速模式的动画
- mysql - 是否可以将表中包含数据的单个列复制到同一架构中的另一个表中?
- pytorch - 为什么在 Pytorch 中打印 GPU 张量的值需要这么长时间?
- google-sheets - 匹配整个列的串联?
- date - I need to change the format of the date