

# 撤离过程
<a name="bp-global-table-design.prescriptive-guidance.evacuation"></a>

撤离区域是指将活动（通常是读取和写入活动，也可能是读取活动）从该区域迁移出去的过程。

## 撤离实时区域
<a name="bp-global-table-design.prescriptive-guidance.evacuation.live"></a>

您可能会出于多种原因决定撤离活动区域：作为日常业务活动的一部分（例如，如果您使用“跟随太阳”、“写入一个区域”模式），由于业务决策需要更改当前主动的区域，为了应对 DynamoDB 外部软件堆栈中的故障，或者因为您遇到了一般问题，例如区域内的延迟高于正常水平。

在*写入任何区域*模式下，撤出实时区域很简单。您可以使用任何路由系统将流量路由到备用区域，并让已撤离区域中的写入操作照常复制。

“写入一个区域”模式和“写入您的区域”模式通常与 MREC 表一起使用。因此，在新的主动区域中开始写入操作之前，您必须确保对主动区域的所有写入操作都已完全记录、流处理并全局传播，以确保将来的写入操作是针对最新版本的数据进行处理的。

假设区域 A 处于主动状态，区域 B 处于被动状态（无论是对于整个表，还是对于以区域 A 为主区域的项目）。执行撤离的典型机制是暂停对 A 的写入操作，等待足够长的时间让这些操作完全传播到 B，更新架构堆栈以识别 B 处于主动状态，然后恢复对 B 的写入操作。没有任何指标可以绝对肯定地表明区域 A 已将其数据完全复制到区域 B。如果区域 A 运行状况正常，暂停对区域 A 的写入操作并等待 `ReplicationLatency` 指标的最近最大值的 10 倍，通常足以确定复制完成。如果区域 A 运行状况不佳且显示延迟增加的其他区域，则应为等待时间选择更大的倍数。

## 撤离离线区域
<a name="bp-global-table-design.prescriptive-guidance.evacuation.offline"></a>

有一个特殊情况需要考虑：如果区域 A 在没有通知的情况下完全离线，会怎样？ 这种情况发生的可能性极低，但仍应考虑在内。

撤离离线 MRSC 表  
如果 MRSC 表发生这种情况，您无需执行任何特殊操作。MRSC 表支持恢复点目标（RPO）为零。对离线区域中的 MRSC 表进行的所有成功写入操作都将在所有其他区域表中可用，因此即使区域在未发出通知的情况下完全离线，也不会出现数据缺失的情况。业务可以继续使用位于其他区域的副本。

撤离离线 MREC 表  
如果 MREC 表发生这种情况，则区域 A 中尚未传播的任何写入操作都将保留，并在区域 A 恢复在线后进行传播。写入操作不会丢失，但它们的传播会被无限期延迟。  
在这种情况下，如何继续操作将由应用程序决定。为了实现业务连续性，写入操作可能需要继续指向新的主区域 B。但是，如果区域 B 中的某个项目收到更新，而针对该项目的写入操作有来自区域 A 的挂起传播，则在*以最后写入者为准*模型下，该传播将被抑制。区域 B 中的任何更新都可能抑制传入的写入请求。  
在*写入任何区域*模式下，可以在区域 B 中继续读取和写入操作，同时相信区域 A 中的项目最终会传播到区域 B，并认识到在区域 A 恢复在线之前可能会丢失项目。如果可能，例如对于幂等的写入操作，您应考虑重播新近的写入流量（例如，使用上游事件源），以填补任何可能缺失的写入操作的空白，并让以最后写入者为准冲突解决方案来抑制传入写入操作的最终传播。  
对于其他写入模式，您必须考虑在多大程度上可以继续工作，而对工作环境的看法稍微过时。在区域 A 恢复在线之前，将丢失一些持续时间很短的写入操作（由 `ReplicationLatency` 跟踪）。业务能否向前推进？ 在某些使用案例中可以向前推进，但在另一些使用案例中，如果没有额外的缓解机制，则可能不行。  
例如，假设即使某个区域完全中断服务，您也必须保持可用的抵扣金余额，不得中断。您可以将余额拆分为两个不同的项目，一个位于主区域 A 中，另一个位于区域 B 中，每个项目从可用余额的一半开始。这将使用*写入您的区域*模式。在每个区域中处理的事务性更新将写入余额的本地副本。如果区域 A 变为完全离线，则仍然可以在区域 B 中继续进行事务处理，写入操作将仅限于区域 B 中持有的余额部分。当余额变低或必须重新计算信贷余额时，像这样拆分余额会带来复杂性，但它确实提供了一个安全业务恢复的示例，即使存在不确定的待处理写入操作。  
再举一个例子，假设您正在捕获 Web 表单数据。您可以使用[乐观并发控制（OCC）](DynamoDBMapper.OptimisticLocking.md)为数据项目分配版本，并将最新版本作为隐藏字段嵌入到 Web 表单中。在每次提交时，只有当数据库中的版本仍然与构建表单所依据的版本相匹配时，写入操作才会成功。如果版本不匹配，则可以根据数据库中的当前版本刷新（或谨慎合并）Web 表单，然后用户可以再次继续。OCC 模型通常可以防止其他客户端覆盖并生成新版本的数据，但它也可以在失效转移期间提供帮助，此时客户端可能会遇到更旧版本的数据。假设您使用时间戳作为版本。表单最初是在 12:00 针对区域 A 构建的，但是（失效转移后）尝试写入区域 B 并注意到数据库中的最新版本是 11:59。在这种情况下，客户端可以等待 12:00 版本传播到区域 B，然后在该版本之上进行写入；也可以在 11:59 上构建并创建新的 12:01 版本（写入后，该版本将在区域 A 恢复后抑制传入版本）。  
第三个例子是，一家金融服务公司在 DynamoDB 数据库中保存有关客户账户及其金融交易的数据。如果区域 A 完全中断，他们希望确保与其账户相关的任何写入活动在区域 B 中完全可用，或者希望将他们的账户作为已知的部分账户进行隔离，直到区域 A 恢复在线。他们没有暂停所有业务，而是决定只对他们确定有未传播交易的一小部分账户暂停业务。为了实现这一点，他们使用了第三个区域，我们称为区域 C。在他们处理区域 A 中的任何写入操作之前，他们在区域 C 中简要地汇总了那些待处理的操作（例如，一个账户的新交易数量）。这个摘要足以让区域 B 确定其视图是否完全是最新的。从在区域 C 中写入操作，到区域 A 接受写入操作并且区域 B 收到写入操作之前，此操作实际上锁定了该账户。除非作为失效转移过程的一部分，否则不会使用区域 C 中的数据，之后，区域 B 可以将其数据与区域 C 进行交叉核对，以检查其账户是否已过期。在区域 A 恢复将部分数据传播到区域 B 之前，这些账户将标记为已隔离。如果区域 C 出现故障，则可以启动一个新的区域 D 以供使用。区域 C 中的数据非常短暂，几分钟后，区域 D 将具有足够新的动态写入操作记录，这将非常有用。如果区域 B 出现故障，区域 A 可以继续接受与区域 C 合作的写入请求。这家公司愿意接受延迟更高的写入（写入到两个区域：C，然后是 A），并且很幸运有了一个可以简洁汇总账户状态的数据模型。