

# 全局表：工作原理
<a name="globaltables_HowItWorks"></a>

**重要**  
 本文档适用于版本 2017.11.29（旧版）的全局表，对于新的全局表，应避免使用该版本。客户应尽可能使用[全局表版本 2019.11.21（当前版）](GlobalTables.md)，因为相比 2017.11.29（旧版），它提供了更大的灵活性、更高的效率并且消耗的写入容量更少。  
要确定正在使用的版本，请参阅[确定全局表的版本](V2globaltables_versions.md#globaltables.DetermineVersion)。要将现有全局表从版本 2017.11.29（旧版）更新到版本 2019.11.21（当前版），请参阅[DynamoDB 全局表版本](V2globaltables_versions.md)。

 以下部分可帮助您了解 Amazon DynamoDB 中全局表的概念和行为。

## 版本 2017.11.29（旧版）的全局表概念
<a name="globaltables_HowItWorks.KeyConcepts"></a>

*全局表*是一个或多个副本表的集合，它们都由单个 AWS 账户所有。

*副本表*（或*副本*）是单个 DynamoDB 表，它作为全局表的一部分发挥作用。每个副本都存储相同的数据项目集。任何给定的全局表在每个 AWS 区域只能有一个副本表。

以下是如何创建全局表的概念概述。

1. 在 AWS 区域中启用 DynamoDB Streams 的情况下创建一个普通的 DynamoDB 表。

1. 对要复制数据的每个其他区域重复步骤 1。

1. 根据您创建的表定义 DynamoDB 全局表。

这些区域有：AWS 管理控制台 会自动执行这些任务，因此您可以更快、更轻松地创建全局表。有关更多信息，请参阅 [创建全局表（版本 2017.11.29）](globaltables.tutorial.md)。

生成的 DynamoDB 全局表包含多个副本表（每个区域一个），DynamoDB 将这些表视为一个单元。每个副本都具有相同的表名和相同的主键架构。当应用程序将数据写入一个区域中的副本表时，DynamoDB 会自动将写操作传播到其他 AWS 区域的其他副本表。

**重要**  
为使表数据保持同步，全局表会自动为每个项目创建以下属性：  
`aws:rep:deleting` 
`aws:rep:updatetime` 
`aws:rep:updateregion` 
请勿修改这些属性或创建具有相同名称的属性。

您可以将副本表添加到全局表中，以便在其他区域中可用。（为此，全局表必须为空。换句话说，任何副本表都不能包含任何数据。）

您还可以从全局表中删除副本表。如果执行此操作，则表与全局表完全断开关联。此新独立表不再与全局表交互，并且数据不再传播到全局表或从全局表传播。

**警告**  
请注意，删除副本不是原子过程。为确保行为的一致性和已知状态，您可能需要考虑提前将应用程序写入流量从要删除的副本移开。删除副本后，请等到所有副本区域端点显示副本已取消关联，然后再将其作为自己的隔离区域表对其进行任何进一步的写入。

## 常见任务
<a name="V2globaltables_HowItWorks.CommonTasks"></a>

全局表的常见任务如下所示。

您可以像删除常规表一样删除全局表的副本表。这将停止复制到该区域并删除保留在该区域的表副本。您无法在切断复制后，让表的副本作为独立实体存在。

**注意**  
在使用源表启动新区域后的至少 24 小时之内，您无法删除该源表。如果您尝试过早将其删除，则会收到错误。

如果应用程序大约在同一时间更新不同区域中的同一项目，则可能会发生冲突。为了帮助确保最终一致性，DynamoDB 全局表使用“最后一个写入方为准”方法来协调并发更新。所有副本都将同意最新的更新，并收敛到它们都具有相同数据的状态。

**注意**  
避免冲突的方法有几种，其中包括：  
使用 IAM 策略以便仅允许写入一个区域中的表。
使用 IAM 策略将用户仅路由到一个区域，而将另一个区域留作空闲备用区域，或者交替地将奇数用户路由到一个区域，而将偶数用户路由到另一个区域。
避免使用诸如 Bookmark = Bookmark \$1 1 之类的非幂等更新，转而使用诸如 Bookmark=25 之类的静态更新。

## 监控全局表
<a name="monitoring-global-tables"></a>

您可以使用 CloudWatch 来观察指标 `ReplicationLatency`。该指标跟踪从 DynamoDB 流显示副本表的更新项目，到该项目出现在全局表的另一个副本中之间经过的时间。`ReplicationLatency` 以毫秒表示，并针对每个源区域和目标区域对发出。这是 Global Tables v2 提供的唯一 CloudWatch 指标。

观察到的延迟取决于所选区域之间的距离以及其他变量。在同一地理区域内，各区域的延迟常常在 0.5 到 2.5 秒范围内。

## 生存时间（TTL）
<a name="global-tables-ttl"></a>

您可以使用生存时间（TTL）来指定一个属性名称，其值表示项目的过期时间。此值以自 Unix 纪元开始以来的秒数指定。

在旧版全局表中，TTL 删除不会自动复制到其它副本中。通过 TTL 规则删除项目时，删除工作是在不消耗写入单位的情况下执行的。

请注意，如果源表和目标表的预调配写入容量非常低，这可能会导致节流，因为 TTL 删除需要写入容量。

## 使用全局表的流和事务
<a name="global-tables-streams"></a>

每个全局表都基于其所有写入生成一个独立的流，而不考虑这些写入的起点。您可以选择在一个区域或在所有区域中单独使用此 DynamoDB 流。

如果您想要已处理的本地写入而不是复制的写入，则可以为每个项目添加您自己的区域属性。然后，您可以使用 Lambda 事件筛选条件，以仅调用 Lambda 在本地区域中进行写入。

事务操作仅在最初进行写入的区域内提供 ACID（原子性、一致性、隔离性和持久性）保证。全局表中不支持跨区域的事务。

例如，如果您有一个全局表，该表在美国东部（俄亥俄州）和美国西部（俄勒冈州）区域中具有副本，并且在美国东部（俄亥俄州）区域中执行 TransactWriteItems 操作，则在复制更改时，可能会在美国西部（俄勒冈州）区域观察到部分完成的事务。更改仅在源区域中提交后才会复制到其他区域。

**注意**  
全局表通过直接更新 DynamoDB 来“绕过”DynamoDB Accelerator。因此，DAX 不会意识到它持有的是陈旧的数据。DAX 缓存只有在缓存的 TTL 过期时才会刷新。
全局表上的标签不会自动传播。

## 读写吞吐量
<a name="V2globaltables_HowItWorks.Throughput"></a>

全局表通过以下方式管理读写吞吐量。
+ 跨区域的所有表实例上的写入容量必须相同。
+ 在版本 2019.11.21（当前版）中，如果表设置为支持自动扩缩或处于按需模式，则写入容量会自动保持同步。在这些同步的自动扩缩设置中，每个区域中预调配的当前写入容量将独立上升和下降。如果表处于按需模式，则该模式将同步到其他副本。
+ 读取容量可能因区域而异，因为读取量可能不相等。在向表添加全局副本时，会传播源区域的容量。创建后，您可以调整一个副本的读取容量，而且此新设置不会传输到另一端。

## 一致性和冲突解决
<a name="globaltables_HowItWorks.conflict-resolution"></a>

对任何副本表中任何项目所做的任何更改都将复制到同一全局表中的所有其他副本中。在全局表中，新写入的项目通常会在几秒钟内传播到所有副本表。

对于全局表，每个副本表都存储相同的数据项集。DynamoDB 不支持仅部分项目的部分复制。

应用程序可以读取数据和将数据写入任何副本表。DynamoDB 支持跨区域的最终一致读取，但不支持跨区域的强一致性读取。如果您的应用程序只使用最终一致性读取，并且仅针对一个 AWS 区域，它将无需任何修改工作。但是，如果您的应用程序需要强一致性读取，它必须在同一区域中执行其所有强一致性读取和写入。否则，如果您写入一个区域并从另一个区域读取，则读取响应可能包含过时的数据，这些数据不反映最近在另一个区域中完成的写入的结果。

如果应用程序大约在同一时间更新不同区域中的同一项目，则可能会发生冲突。为了帮助确保最终的一致性，DynamoDB 全局表使用*最后一个写入方为准*协调并发更新，DynamoDB 会尽最大努力确定最后一个写入方。使用此冲突解决机制，所有副本都将同意最新的更新，并收敛到它们都具有相同数据的状态。

## 可用性与持久性
<a name="globaltables_HowItWorks.availability-durability"></a>

如果单个 AWS 区域变得孤立或降级，您的应用程序可以重定向到不同的区域，并对其他副本表执行读取和写入操作。您可以应用自定义业务逻辑来确定何时将请求重定向到其他区域。

如果某个区域被隔离或降级，DynamoDB 会跟踪已执行但尚未传播到所有副本表的任何写入操作。当区域恢复联机时，DynamoDB 将继续将任何挂起的写入从该区域传播到其他区域中的副本表。它还会继续将写入从其他副本表传播到现在重新联机的区域。无论该区域被隔离多长时间，所有以前成功的写入都将最终得到传播。