亚马逊AWS官方博客

新 – Amazon DynamoDB 事务

多年以来,客户将 Amazon DynamoDB 用于众多不同的使用案例,从建筑微服务和移动后端到部署游戏和物联网 (IoT) 解决方案,不一而足。例如,Capital One 使用 DynamoDB 将其主机事务移至无服务器架构,从而减少其移动应用程序的延迟。 Tinder 零停机时间将用户数据迁移到 DynamoDB,以获得支持其全球用户群所需的可扩展性。

有时,开发人员需要部署要求在一个或多个表单之间进行多个全有或全无操作的业务逻辑。这种要求可能会为其部署增加不必要的复杂性。如今,我们通过对这些事务的原生支持,让这些使用案例在 DynamoDB 上的构建变得更加简单!

推出 Amazon DynamoDB 事务

DynamoDB 事务可让开发人员在单个 AWS 帐户和区域内的一个或多个表单中实现原子性、一致性、隔离性和持久性 (ACID)。 构建需要在单个逻辑业务操作中包含对多个项的协调插入、删除或更新的应用程序时,您可以使用这些事务。DynamoDB 是支持跨多个分区和表单的事务的唯一非关系数据库。

这些事务让更广泛的工作负载获得 DynamoDB 的规模、性能和企业优势。使用事务,许多使用案例部署起来更轻松且更快,例如:

  • 处理财政事务
  • 履行和管理订单
  • 构建多层游戏引擎
  • 协调分布式组件和服务之间的操作

为处理事务推出了两种新 DynamoDB 操作:

  • TransactWriteItems,这种批操作包含写集合,其中有一个或多个 PutItem、UpdateItem 和 DeleteItem 操作。TransactWriteItems 能够可选地检查进行更新之前必须满足的前提条件。 这些条件可能涉及与写集合中的项相同或不同的项。如果未满足任何条件,事务将被拒绝。
  • TransactGetItems,这种批操作包含读集合,其中有一个或多个 GetItem 操作。如果对活动写事务中的项发布了 TransactGetItems 请求,则读事务将被取消。为了获得先前提交的值,您可以使用标准读事务。

每个事务可以包含最多 10 个唯一项或最多 4 MB 的数据,包括条件。

通过这种新特性,DynamoDB 可提供多种读写选项以满足不同的应用程序要求,为部署复杂的数据驱动型业务逻辑的开发人员带来巨大的灵活性:

  • 读事务的三个选项—最终一致性、强一致性和事务。
  • 写事务的两个选项—标准和事务。

例如,假定您正在构建玩家可使用虚拟金币购买物品的游戏:

  • 玩家表单中,每个玩家都有一些金币以及所购物品的库存
  • 物品表单中,每种物品都有自己的价格并通过布尔值标记为可用(或不可用)。

为了购买物品,现在您可以部署单个原子事务:

  1. 首先,检查可用的物品以及玩家是否有足够的金币
  2. 如果满足这些条件,该物品将标记为不可用且归玩家拥有
  3. 然后,所购买的物品添加到玩家的库存列表。

在 JavaScript 中,使用 Node.js 格式的 AWS SDK for JavaScript,您将可获得与下文类似的代码:

data = await dynamoDb.transactWriteItems({
    TransactItems: [
        {
            Update: {
                TableName: 'items',
                Key: { id: { S: itemId } },
                ConditionExpression: 'available = :true',
                UpdateExpression: 'set available = :false, ' +
                    'ownedBy = :player',
                ExpressionAttributeValues: {
                    ':true': { BOOL: true },
                    ':false': { BOOL: false },
                    ':player': { S: playerId }
                }
            }
        },
        {
            Update: {
                TableName: 'players',
                Key: { id: { S: playerId } },
                ConditionExpression: 'coins >= :price',
                UpdateExpression: 'set coins = coins - :price, ' +
                    'inventory = list_append(inventory, :items)',
                ExpressionAttributeValues: {
                    ':items': { L: [{ S: itemId }] },
                    ':price': { N: itemPrice.toString() }
                }
            }
        }
    ]
}).promise();

使用事务

默认情况下,事务对所有单区域 DynamoDB 表单启用,而对全局表单禁用。您可以选择按请求对全局表单启用事务,但是跨区域复制为异步且最终一致。在复制到其他区域的过程中,您可以部分地观察已完成的事务。此外,无法保证对不同区域中的相同项进行的同步写入事务实现串行隔离。

在事务发生期间,这些项未被锁定。DynamoDB 事务提供串行化隔离。如果在事务进行过程中修改了事务之外的项,则将取消事务,并设置例外,同时提供关于哪些项导致该例外的详细信息。

创建 AWS Identity and Access Management (IAM) 策略时,没有关于 TransactGetItems 和 TransactWriteItems 的新权限。现有的 DynamoDB UpdateItem、PutItem、DeleteItem 和 GetItem 操作授权也在事务内使用这些操作。例如,如果 IAM 用户只有 PutItem 权限,则他们可以发送包含一个或多个 put 的事务,但是如果他们向写集合中添加了 delete,则将被拒绝,因为他们没有 DeleteItem 权限。

对于事务中的任何已执行操作,DynamoDB Streams 都会添加一个新字段 transaction-id,作为事务的通用唯一识别码 (UUID)。DynamoDB Streams 按顺序出现的仅一次执行语义保证 TransactWriteItems 请求的所有更新最终按照与事务串行化顺序一致的顺序通过流传播。

定价、监控和可用性

为 DynamoDB 表单启用事务不会产生额外的成本。您只需为事务中的读或写付费。DynamoDB 对事务中的每一项执行底层读或写,一个用于准备事务,另一个用于提交事务。 两种底层读/写操作都在您的 CloudWatch 指标中可见。您应规划成本、容量和性能需要,假定每个事务性读取操作都执行两种读取,每个事务性写入操作都执行两种写入。

DynamoDB 事务在全球所有商业区域均可获得。

我真的迷上了这些新功能。快告诉我您打算将它用在哪些方面吧!