Amazon dynamodb 更改DynamoDB表的模式:最佳/推荐的方法是什么?

Amazon dynamodb 更改DynamoDB表的模式:最佳/推荐的方法是什么?,amazon-dynamodb,Amazon Dynamodb,Amazon推荐的在生产DynamoDB中更改大表模式的方法是什么 设想一个假设的情况,其中我们有一个表Person,其主散列键为SSN。此表可能包含1000万项 现在有消息说,由于身份盗窃案数量巨大,这个假想国家的政府引入了另一种个人身份:唯一个人识别码(Unique personal Identifier,简称UPI) 我们必须添加一个UPI列并更改Person表的模式,以便现在主哈希键是UPI我们希望在一段时间内支持使用SSN的当前系统和使用UPI的新系统,因此我们需要这两列在Person

Amazon推荐的在生产DynamoDB中更改大表模式的方法是什么

设想一个假设的情况,其中我们有一个表Person,其主散列键为SSN。此表可能包含1000万项

现在有消息说,由于身份盗窃案数量巨大,这个假想国家的政府引入了另一种个人身份:唯一个人识别码(Unique personal Identifier,简称UPI)

我们必须添加一个UPI列并更改Person表的模式,以便现在主哈希键是UPI我们希望在一段时间内支持使用SSN的当前系统和使用UPI的新系统,因此我们需要这两列在Person表中共存


Amazon推荐的更改模式的方法是什么?

有几种方法,但首先您必须了解,您不能更改现有表的模式。要获得不同的模式,必须创建一个新表。您可以重用现有表,但结果与创建其他表时相同

  • 懒散地迁移到同一个表,没有流。每次修改Person表中的条目时,使用UPI而不是SSN作为哈希键的值在Person表中创建一个新项,并删除在SSN处键入的旧项。这假设UPI的取值范围与SSN不同。如果SSN看起来像XXX-XX-XXXX,那么只要UPI的位数与SSN的位数不同,您就永远不会有重叠
  • 使用流延迟迁移到同一个表。当流变得普遍可用时,您将能够为Person表打开流。创建一个具有“新”和“旧”图像流视图类型的流,并且每当您检测到对某个项的更改,该项将UPI添加到person表中的现有person时,创建一个Lambda函数,该函数将删除在SSN处键入的person,并添加具有在UPI处键入的相同属性的person。这种方法具有竞争条件,可以通过向项添加原子计数器版本属性并在版本属性上调整DeleteItem调用来缓解竞争条件
  • 使用流,抢占式(脚本化)迁移到不同的表。运行一个脚本,扫描您的表并向Person表中的每个Person项添加唯一的UPI。使用NEW_和_OLD_IMAGES流视图类型创建一个stream on Person表,并向该流订阅lambda函数,当lambda函数检测到具有UPI的人员已更改或添加了UPI时,该函数会将所有新人员写入一个NEW Person_UPI表。基表上的突变通常需要数百毫秒才能作为流记录出现在流中,因此您可以对应用程序中的新Person_UPI表进行热故障切换。拒绝请求几秒钟,在此期间将应用程序指向Person_UPI表,然后重新启用请求

  • 我使用的是亚历山大第三种方法的变体。再次创建一个新表,该表将随着旧表的更新而更新。不同之处在于,在转换时使用现有服务中的代码写入两个表,而不是使用lambda函数。您可能有不希望在临时lambda函数中重现的自定义持久性代码,而且您可能必须为这个新表编写服务代码。根据您的体系结构,您甚至可以在不停机的情况下切换到新表


    但是,使用lambda函数的好处在于,对新表的额外写入所引入的任何负载都将在lambda上,而不是在服务上。

    DynamoDB streams使我们能够在不停机的情况下迁移表。我这样做非常有效,我遵循的步骤是:

  • 创建一个新表(我们称之为NewTable),该表具有所需的键结构LSIs和GSIs
  • 在原始表上启用DynamoDB流
  • 将Lambda与流关联,从而将记录推送到新表中。(此Lambda应在步骤5中删除迁移标志)
  • [可选]在原始表上创建GSI以加快扫描项目。确保此GSI只有属性:主键和已迁移(请参阅步骤5)
  • 扫描在上一步中创建的GSI(或整个表),并使用以下过滤器:

    FilterExpression=“属性不存在(已迁移)”

  • 使用migrate标志(即:“Migrated”:{“S”:“0”})更新表中的每个项,该标志将其发送到DynamoDB流(使用UpdateItem API,以确保不会发生数据丢失)

    注意:您可能希望在更新期间增加表上的写入容量单位

  • Lambda将拾取所有项,修剪迁移的标志并将其推入新表
  • 迁移完所有项后,将代码重新指向新表
  • 去掉原来的表,和Lambda函数一次高兴都好
  • 遵循这些步骤可以确保您没有数据丢失和停机

    我已经在我的博客上记录了这一点,并提供了代码帮助:

    如果更改涉及更改分区键,则可以添加新的GSI(全局二级索引)。此外,您可以随时向DynamoDB添加新列/属性,而无需迁移表。

    感谢建议的解决方案。如何处理其他表中的外键,这些表包含个人SSN作为其属性之一的值?我需要更新一个原子操作中的所有列/属性,否则可能存在竞争条件。好了吗DynamoDB中不是官方的事务机制吗?我偶然发现了一个事务库,但它是用Java编写的,据说落后于最新版本的DynamoDB。有什么事务机制可以在Python中使用(使用Boto)吗?好的,事务库是打开的