用于查询多值属性的DynamoDB表/索引架构设计

时间:2018-12-06 22:57:35

标签: amazon-web-services amazon-dynamodb dynamodb-queries

我正在构建一个DynamoDB应用程序,该应用程序最终将为大量(数百万)用户提供服务。目前,应用程序的项目架构很简单:

{ 
  userId: "08074c7e0c0a4453b3c723685021d0b6",  // partition key
  email: "foo@foo.com",
  ... other attributes ...
}

当新用户注册时,或者如果一个用户想要通过电子邮件地址找到另一个用户,我们将需要按email而不是userId查找用户。使用当前的模式很容易:只需使用带有email作为分区键的全局二级索引即可。

但是我们想为每个用户启用多个电子邮件地址,并且DynamoDB Query操作不支持List类型的KeyConditionExpression。因此,我正在权衡几种选择,以避免每次用户注册或希望通过电子邮件地址找到另一个用户时进行昂贵的Scan操作。

以下是我打算更改的功能,以为每个用户启用其他电子邮件。这是一个好方法吗?有更好的选择吗?

  1. 添加一个排序键列(例如itemTypeAndIndex)以允许每个userId有多个项目。

{ userId: "08074c7e0c0a4453b3c723685021d0b6", // partition key itemTypeAndIndex: "main", // sort key email: "foo@foo.com", ... other attributes ... }

  1. 如果用户添加第二,第三等电子邮件,则为每封电子邮件添加一个新项目,如下所示:

{ userId: "08074c7e0c0a4453b3c723685021d0b6", // partition key itemTypeAndIndex: "Email-2", // sort key email: "bar@bar.com" // no more attributes }

  1. 相同的全局二级索引(使用email作为分区密钥)仍可用于查找主要和非主要电子邮件地址。

  2. 如果用户想更改其主要电子邮件地址,我们将在“主要”和“非主要”项目中交换email值。 (现在DynamoDB支持transactions,这样做会比以前更安全!)

  3. 如果我们需要删除用户,则必须删除该userId的所有项目。如果我们需要合并两个用户,则必须合并该userId的所有项目。

  4. 可以将相同的方法(具有相同userId但排序键不同的新项目)用于需要Query的其他1-user-has-man-values数据

这是一个好方法吗?有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

Justin,在搜索属性时,我强烈建议不要使用DynamoDB。我并不是说,您无法实现这一目标。但是,如果您扎根,我发现最终会遇到一些问题。

  1. 在email-id上使用sort-key将导致为同一用户创建重复的记录,即,如果一个用户注册了5封电子邮件,则意味着表中的5条记录具有相同的模式和属性(email-id属性除外)。 / li>
  2. 如果将来出现新的用例怎么办,现在您还希望在此基于其他属性(例如,手机号码,假设一个用户可能拥有一个以上的手机号码)来搜索用户< / li>
  3. DynamoDB有一个hard limit of the number of secondary indexes,您可以为表创建一个Kibana UI

因此,随着搜索条件用例的增加,该解决方案将很容易成为您系统的瓶颈。因此,您的系统可能无法很好地扩展。


据我所知,我可以根据您的要求/预算建议一些选项,以使用多个数据库来解决此问题。

Option 1. DynamoDB作为主要存储,AWS Elasticsearch作为辅​​助存储[首选]

  1. 在用户注册时将用户记录存储在DynamoDB表中(简称为 UserTable )。
  2. UserTable 表上启用DynamoDB表流。
  3. 构建一个AWS Lambda函数,该函数从表的流中读取并将记录保留在AWS Elasticsearch中。

现在,在您的应用程序中,使用DynamoDB从ID中获取用户记录。对于所有其他搜索条件(例如搜索emailId,电话号码,邮政编码,位置等),请从AWS Elasticsearch获取记录。默认情况下,AWS Elasticsearch对记录的所有属性建立索引,因此您可以在延迟的毫秒内搜索任何字段。

Option 2. 使用AWS Aurora [更少的首选解决方案]

如果您的应用程序具有与数据相关的关系用例,则可以考虑使用此选项。只是请注意,Aurora是一个SQL数据库。 由于这是一个关系存储,因此您可以选择组织多个表中的记录,并根据这些表的主键将它们连接起来。



我建议第一种选择为:

  1. DynamoDB将为您的应用程序提供持久,高可用性,低延迟的主存储。
  2. AWS Elasticsearch将充当辅助存储,这也是持久,可伸缩且低延迟的存储。
  3. 使用AWS Elasticsearch,您可以在表上运行任何搜索查询。您还可以对数据进行分析。 {{3}}开箱即用,可用于在仪表板上绘制分析数据,例如(用户增长趋势,特定位置的用户数量,基于城市/州/国家/地区的用户分布等)
  4. 借助DynamoDB流和AWS Lambda,您将在几毫秒内几乎实时地同步这两个数据库
  5. 您的应用程序将具有可伸缩性,并且搜索功能可以进一步增强以对多级属性进行过滤。 [一个例子:搜索属于给定城市的所有用户]

话虽如此,现在我将由您决定。