And*_*708 4 notifications amazon-web-services amazon-dynamodb
我将实现一个通知系统,我试图找出一种在数据库中存储通知的好方法.我有一个使用PostgreSQL数据库的Web应用程序,但关系数据库似乎不适合这个用例; 我想支持各种类型的通知,每种通知都包含不同的数据,但数据的子集对于所有类型的通知都是通用的.因此,我认为NoSQL数据库可能比尝试规范化关系数据库中的模式更好,因为这将非常棘手.
我的应用程序托管在Amazon Web Services(AWS)中,我一直在寻找DynamoDB来存储通知.这是因为它是受管理的,所以我不必处理它的操作.理想情况下,我想使用MongoDB,但我真的不想自己不必处理数据库的操作.我一直试图想出一种在DynamoDB中做我想做的事情的方法,但我一直在努力,因此我有几个问题.
假设我想为每个通知存储以下数据:
现在,我希望能够查询给定用户的最新X通知.此外,在另一个查询中,我想获取特定用户的未读通知数.我试图找出一种方法,我可以索引我的表,以便能够有效地做到这一点.
我可以排除简单地使用哈希主键,因为我不会通过简单的哈希键进行查找.我不知道"散列和范围主键"是否会对我有所帮助,因为我不知道将哪个属性作为范围键.我可以将唯一通知ID作为散列键,将用户ID作为范围键吗?这是否允许我仅通过范围键进行查找,即不提供哈希键?那么也许二级索引可以帮助我按时间戳排序,如果这是可能的话.
我还查看了全局二级索引,但问题是查询索引时,DynamoDB只能返回投射到索引中的属性 - 因为我希望返回所有属性,那么我实际上必须复制我的所有数据,看起来都很荒谬.
如何索引我的通知表以支持我的用例?它甚至可能,或者你有任何其他建议吗?
动机注意:使用像DynamoDB这样的云存储时,我们必须了解存储模型,因为这会直接影响您的性能,可扩展性和财务成本.它与使用本地数据库不同,因为您不仅要为您存储的数据付费,还要为您对数据执行的操作付费.例如,删除记录是WRITE操作,因此如果您没有有效的清理计划(并且您的情况是时间序列数据特别需要),您将支付价格.处理小数据量时,您的数据模型不会出现问题,但在需要扩展时肯定会破坏您的计划.话虽这么说,创建(或不创建)索引,为键定义正确的属性,创建表格分段等等决策将使整个过程变得无与伦比.选择DynamoDB(或者更一般地说,键值存储)与任何其他架构决策一样需要权衡,您需要清楚地理解有关存储模型的某些概念,以便能够有效地使用该工具,选择正确的密钥确实很重要,但只是冰山一角.例如,如果您忽略了处理时间序列数据这一事实,无论您定义了哪个主键或索引,您的预配置吞吐量都不会被优化,因为它遍布整个表(及其分区)而不仅仅是经常访问的数据,意味着未使用的数据直接影响您的吞吐量,因为它是同一个表的一部分.这会导致
ProvisionedThroughputExceededException当您确定您的预配置吞吐量足以满足您的需求时"意外"抛出的情况,但是,不均匀访问的TABLE PARTITION已达到其限制(此处有更多详细信息).
下面的帖子有更多的细节,但我想给你一些动力来阅读它并理解虽然你现在肯定可以找到一个更简单的解决方案,但这可能意味着在你不久的将来当你碰壁时从头开始( "墙"可能会带来高昂的财务成本,性能和可扩展性的限制,或者所有的组合.
问:我可以将唯一通知ID作为哈希键,将用户ID作为范围键吗?这是否允许我仅通过范围键进行查找,即不提供哈希键?
答: DynamoDB是一个键值存储,意味着最有效的查询使用整个密钥(散列或散列范围).Scan仅仅因为没有密钥而使用该操作来实际执行查询,这无疑表明您的数据模型在您的需求方面存在缺陷.有几点需要考虑,有很多选项可以避免这个问题(详见下文).
在继续之前,我建议你阅读这篇快速文章,以清楚地理解Hash Key和Hash + Range Key之间的区别:
您的案例是典型的时间序列数据场景,随着时间的推移,您的记录将变得过时.您需要注意两个主要因素:
如果将所有通知放在一个表中,并且更频繁地访问最新的通知,则无法有效使用预配置的吞吐量.您应该将访问最多的项目分组到一个表中,以便可以针对所需的访问权限正确调整预配置的吞吐量.此外,请确保正确定义哈希密钥,以便在多个分区之间均匀分布数据.
文档建议将数据分段到不同的表中,以便在记录过时后删除或备份整个表(请参阅下面的详细信息).
以下是解释与时间序列数据相关的最佳实践的文档部分:
了解时间序列数据的访问模式
对于您创建的每个表,您可以指定吞吐量要求.DynamoDB通过持续的低延迟分配和预留资源来处理吞吐量要求.在设计应用程序和表时,应考虑应用程序的访问模式,以便最有效地使用表的资源.
假设您设计了一个表来跟踪您网站上的客户行为,例如他们点击的网址.您可以使用散列和范围类型主键设计表,其中Customer ID作为散列属性,日期/时间作为range属性.在此应用程序中,客户数据随着时间的推移无限增长; 但是,应用程序可能会在表中的所有项目中显示不均匀的访问模式,其中最新的客户数据更相关,并且您的应用程序可能更频繁地访问最新项目,并且随着时间的推移这些项目访问较少,最终旧项目很少访问.如果这是一种已知的访问模式,则可以在设计表模式时将其考虑在内.您可以使用多个表来存储这些项,而不是将所有项存储在单个表中.例如,您可以创建表来存储月度或每周数据.对于存储数据访问率较高的最近一个月或一周的数据的表,请求更高的吞吐量,对于存储旧数据的表,您可以调低吞吐量并节省资源.
您可以通过将"热"项存储在具有较高吞吐量设置的一个表中,并将"冷"项存储在具有较低吞吐量设置的另一个表中来节省资源.您只需删除表即可删除旧项.您可以选择将这些表备份到其他存储选项,例如Amazon Simple Storage Service(Amazon S3).删除整个表比逐个删除项目效率要高得多,这实际上使写入吞吐量翻了一倍,就像执行put操作一样多的删除操作.
资源:
例如,您可以按月对表进行分段:
Notifications_April, Notifications_May, etc
Run Code Online (Sandbox Code Playgroud)
问:我希望能够查询给定用户的最新X通知.
答:我建议使用Query操作和查询,只使用Hash Key(UserId)Range Key按Timestamp(日期和时间)对通知进行排序.
Hash Key: UserId
Range Key: Timestamp
Run Code Online (Sandbox Code Playgroud)
注意:更好的解决方案是在查询之前Hash Key不仅要获得UserId另外的连接信息,还要确保您Hash Key甚至可以访问数据模式.例如,如果来自特定用户的通知比其他用户更多,则可以开始使用热分区 ...在其中添加其他信息Hash Key可以降低此风险.
问:我想获取特定用户的未读通知数量.
答:创建Global Secondary Index一个稀疏索引具有UserId作为Hash Key和Unread作为Range Key.
例:
Index Name: Notifications_April_Unread
Hash Key: UserId
Range Key : Unuread
Run Code Online (Sandbox Code Playgroud)
当您通过哈希密钥(UserId)查询此索引时,您将自动获得所有未读通知,而不会通过与此案例无关的通知进行不必要的扫描.请记住,表中的原始主键会自动投影到索引中,因此,如果您需要获取有关通知的更多信息,您始终可以使用这些属性来执行原始表GetItem或BatchGetItem原始表.
注意:您可以探索使用"未读"标志以外的其他属性的想法,重要的是要记住,稀疏索引可以帮助您使用此用例(下面有更多详细信息).
详细说明:
我会有一个稀疏索引,以确保您可以查询简化数据集来进行计数.在您的情况下,您可以使用"未读"属性来标记是否已读取通知,并使用该属性创建稀疏索引.当用户阅读通知时,您只需从通知中删除该属性,使其不再显示在索引中.以下是明确适用于您的方案的文档中的一些准则:
利用稀疏索引
对于表中的任何项,如果项中存在索引范围键属性值,DynamoDB将仅写入相应的索引条目.如果范围键属性未出现在每个表项中,则称该索引是稀疏的.[...]
要跟踪未结订单,您可以在CustomerId(哈希)和IsOpen(范围)上创建索引.只有定义了IsOpen的表中的订单才会出现在索引中.然后,您的应用程序可以通过查询索引快速有效地查找仍处于打开状态的订单.例如,如果您有数千个订单,但只有少数订单已打开,则应用程序可以查询索引并返回每个未结订单的OrderId.与扫描整个CustomerOrders表所需的读取相比,您的应用程序执行的读取次数要少得多.[...]
您可以使用不同的属性,而不是将任意值写入IsOpen属性,这将导致索引中的有用排序顺序.为此,您可以创建OrderOpenDate属性并将其设置为下达订单的日期(并且在完成订单后仍然删除该属性),并使用架构CustomerId(hash)和OrderOpenDate创建OpenOrders索引(范围).这样,当您查询索引时,将以更有用的排序顺序返回项目.[...]
这样的查询可以非常有效,因为索引中的项目数量将远远少于表格中的项目数量.此外,您投射到索引中的表属性越少,您将从索引中消耗的读取容量单位就越少.
资料来源:http: //docs.aws.amazon.com/amazondynamodb/latest/developerguide/GuidelinesForGSI.html#GuidelinesForGSI.SparseIndexes
在下面找到一些对以编程方式创建和删除表所需的操作的引用:
创建表 http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_CreateTable.html
删除表 http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DeleteTable.html
| 归档时间: |
|
| 查看次数: |
771 次 |
| 最近记录: |