Getting/Updating DynamoDB 中的一个计数器
Getting/Updating A Counter in DynamoDB
架构问题。作为游戏的一部分,我们希望跟踪所有玩家已完成的物品数量。跟踪玩家状态没问题,dynamo 很好地跨用户分片。但是如果我想要一个显示有多少 X 已被处理的数字,那么我说的是单行 table,这意味着每个更新并从 table 中检索的人都在点击完全相同的行。我很确定 Dynamo 会接受很多这样的东西,但我想知道它的扩展性如何。当每个人执行一个功能时,计数器会递增,然后他们会读回它。
我想我们可以将计数器保存在 memcache 或 Redis 中,并在分类新项目时更新它,并在每晚重建它。这似乎有点矫枉过正,需要额外的基础设施。
有什么想法吗?有没有人成功地做到了这一点? Dynamo 保持跟踪,但他们 return 的数字可能已经过时了六个小时。
这里的主要问题是您真正需要以多快的速度递增该数字。我们通过在名为 "counters" 的系统中使用全局 table,将 Atomic counters 作为我们生产的一部分。我们很少需要每个计数器每秒递增几次以上,因此目前缩放比例不是问题。
这一切都取决于您需要保留(和规模)的计数器的速率和数量。
如果您需要非常快的计数器,我想有更好的方法(例如内存缓存/redis)定期刷新。如果您需要为该规模做好准备,我认为这不是矫枉过正。
是的,如果您期望每秒写入超过 1000 次(单个分区可用的写入数),则由每个人递增的单个项目将无法很好地扩展。如果您预计每秒写入次数少于 1000 次,DynamoDB 允许对单个项目进行强一致性读取(或者,您也可以要求在 UpdateItem 请求的结果中返回更新后的值)
聚合 memcached 或 Redis 中的计数并定期对 DynamoDB 执行 "bulk" 添加(例如添加 1000)肯定有助于随着时间的推移分散访问,如果您需要强一致性,这可能是最好的方法,在发生崩溃时丢失缓存数据是可以接受的table,并且您的可用性要求很低。
如果您不需要强一致性(例如,计数可以更多地视为下限),您可以使用写分片来保留多个计数器以分散访问,以便每个计数器都可以访问每秒少于 1000 次。
然后您可以使用 Scan(如果只有几个小计数,扫描应该不会很昂贵)或多次 GetItem 调用来定期汇总计数。这些 slides.
中对此有一些讨论
或者,如果您可以使用预览区域,则可以在 table 上启用 DynamoDB Streams 并使用 AWS Lambda 函数从 table 流中获取批量计数并聚合计数成一个子计数。重复上述步骤以建立最终计数。这种方法将允许不断汇总总计数,而不是设置定期扫描 activity.
架构问题。作为游戏的一部分,我们希望跟踪所有玩家已完成的物品数量。跟踪玩家状态没问题,dynamo 很好地跨用户分片。但是如果我想要一个显示有多少 X 已被处理的数字,那么我说的是单行 table,这意味着每个更新并从 table 中检索的人都在点击完全相同的行。我很确定 Dynamo 会接受很多这样的东西,但我想知道它的扩展性如何。当每个人执行一个功能时,计数器会递增,然后他们会读回它。
我想我们可以将计数器保存在 memcache 或 Redis 中,并在分类新项目时更新它,并在每晚重建它。这似乎有点矫枉过正,需要额外的基础设施。
有什么想法吗?有没有人成功地做到了这一点? Dynamo 保持跟踪,但他们 return 的数字可能已经过时了六个小时。
这里的主要问题是您真正需要以多快的速度递增该数字。我们通过在名为 "counters" 的系统中使用全局 table,将 Atomic counters 作为我们生产的一部分。我们很少需要每个计数器每秒递增几次以上,因此目前缩放比例不是问题。
这一切都取决于您需要保留(和规模)的计数器的速率和数量。
如果您需要非常快的计数器,我想有更好的方法(例如内存缓存/redis)定期刷新。如果您需要为该规模做好准备,我认为这不是矫枉过正。
是的,如果您期望每秒写入超过 1000 次(单个分区可用的写入数),则由每个人递增的单个项目将无法很好地扩展。如果您预计每秒写入次数少于 1000 次,DynamoDB 允许对单个项目进行强一致性读取(或者,您也可以要求在 UpdateItem 请求的结果中返回更新后的值)
聚合 memcached 或 Redis 中的计数并定期对 DynamoDB 执行 "bulk" 添加(例如添加 1000)肯定有助于随着时间的推移分散访问,如果您需要强一致性,这可能是最好的方法,在发生崩溃时丢失缓存数据是可以接受的table,并且您的可用性要求很低。
如果您不需要强一致性(例如,计数可以更多地视为下限),您可以使用写分片来保留多个计数器以分散访问,以便每个计数器都可以访问每秒少于 1000 次。
然后您可以使用 Scan(如果只有几个小计数,扫描应该不会很昂贵)或多次 GetItem 调用来定期汇总计数。这些 slides.
中对此有一些讨论或者,如果您可以使用预览区域,则可以在 table 上启用 DynamoDB Streams 并使用 AWS Lambda 函数从 table 流中获取批量计数并聚合计数成一个子计数。重复上述步骤以建立最终计数。这种方法将允许不断汇总总计数,而不是设置定期扫描 activity.