

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# MemoryDB 多区域
<a name="multi-region"></a>

MemoryDB 多区域是一个完全托管的、主动-主动的多区域数据库，使您能够构建具有高达 99.999% 可用性、微秒级读取和个位数毫秒写入延迟的多区域应用程序。您可以从区域降级中提高可用性和弹性，同时受益于多区域应用程序的低延迟本地读取和写入。

使用 MemoryDB 多区域，您可以构建高可用的多区域应用程序，以提高弹性。它提供主动-主动复制，因此您可以从最接近客户的区域本地提供读取和写入，具有微秒级读取和个位数毫秒写入延迟。MemoryDB 多区域在区域之间异步复制数据，数据通常在一秒内传播。它会自动解决更新冲突并纠正数据分歧问题，使您能够专注于您的应用程序。

目前，以下区域支持 MemoryDB 多 AWS 区域：美国东部（弗吉尼亚北部和俄亥俄州）、美国西部（俄勒冈、加利福尼亚北部）、欧洲（爱尔兰、法兰克福和伦敦）和亚太地区（东京、悉尼、孟买、首尔和新加坡）。

只需点击几下即可轻松开始使用 MemoryDB 多区域， AWS 管理控制台 或者使用最新的 AWS SDK，或者。 AWS CLI

**Topics**
+ [先决条件和限制](multi-region.prereq.md)
+ [工作原理](multi-region.how.md)
+ [一致性和冲突解决](#multi-region.conflict)
+ [通过控制台使用 MemoryDB 多区域](multi-Region.console.md)
+ [通过 CLI 使用 MemoryDB 多区域](multi-Region.cli.md)
+ [监控 MemoryDB 多区域](multi-Region.monitoring.md)
+ [MemoryDB 多区域扩缩](multi-Region.Scaling.md)
+ [支持与不支持的命令](multi-Region.SupportedCommands.md)

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

对某个区域集群中的键进行的任何更新，通常会在一秒内异步传播到多区域集群中的其他区域集群。如果某个区域被隔离或降级，MemoryDB 多区域会跟踪所有已执行但尚未传播到所有成员集群的写入。当该区域恢复在线时，MemoryDB 多区域会恢复将该区域中任何待处理的写入传播到其他区域的成员集群。它也会恢复将其他成员集群的写入传播到现已恢复在线的区域。无论该区域被隔离多长时间，所有以前成功的写入都将最终得到传播。

如果您的应用程序大约同时在不同区域更新相同的键，则可能产生冲突。MemoryDB 多区域使用无冲突复制数据类型（CRDT）来协调冲突的并发写入。CRDT 是一种可以独立、并发更新而无需协调的数据结构。这意味着写入-写入冲突会在每个副本上独立合并，并最终实现一致性。

具体来说，MemoryDB 使用两级“最后写入者胜出（LWW）”来解决冲突。对于字符串数据类型，LWW 在键级别解决冲突。对于其他数据类型，LWW 在子键级别解决冲突。冲突解决完全由系统托管，并在后台进行，不会对应用程序的可用性产生任何影响。以下是哈希数据类型的一个示例：

区域 A 在时间戳 T1 执行“HSET K F1 V1”；区域 B 在时间戳 T2 执行“HSET K F2 V2”；复制后，区域 A 和 B 都将拥有包含两个字段的键 K。当不同区域并发更新同一集合中的不同子键时，由于 MemoryDB 对哈希数据类型在子键级别解决冲突，这两次更新不会相互冲突。因此，最终数据将包含这两次更新的效果。


| 时间 | 区域 A | 区域 B | 
| --- | --- | --- | 
| T1 |  HSET K F1 V1 |  | 
| T2 |  |  HSET K F2 V2 | 
| T3 | 同步 | 同步 | 
| T4 |  K: {F1:V1, F2:V2} | K: {F1:V1, F2:V2} | 

### CRDT 及示例
<a name="clusters.multi-Region.CRDT"></a>

 MemoryDB 多区域实现了无冲突复制数据类型（CRDT）来解决来自多个区域的并发写入冲突。CRDT 允许不同区域在最终接收到相同操作集后，无论顺序如何，都能独立达成最终一致性。

 当单个键在多个区域中同时被更新时，需要解决写入-写入冲突以实现数据一致性。MemoryDB 多区域使用“最后写入者胜出（LWW）”策略来确定获胜操作，最终只能观察到“后发生”的操作效果。如果操作 op1 的效果在操作 op2 执行时，已在原始执行 op1 的区域中得到应用，则我们说操作 op1“发生在”操作 op2“之前”。

 对于集合（哈希、集合和 SortedSet）MemoryDB 多区域解决元素级别的冲突。这允许 MemoryDB Multi-Region 使用 LWW 来解决每个元素上的 write/write 冲突。例如，从多个区域同时向同一集合添加不同元素，将导致该集合包含所有元素。

**并发执行：最后写入者胜出**

在 MemoryDB 多区域中，当存在键的并发创建时，在任何区域上执行的最后一个操作将决定该键的结果。例如：

![并发执行：最后写入者胜出。](http://docs.aws.amazon.com/zh_cn/memorydb/latest/devguide/images/concurrent-ex-last-writer-wins.png)


键 x 在区域 B 上创建，值为“b”，但此后同一键在区域 A 上创建，值为“a”。由于区域 A 的操作是最后执行的操作，该键最终将收敛为值“a”。

**数据类型冲突的并发执行：最后写入者胜出**

在前面的示例中，该键在两个区域中都是以相同类型创建的。如果该键是以不同数据类型创建的，也会观察到类似的行为：

![数据类型冲突的并发执行：最后写入者胜出。](http://docs.aws.amazon.com/zh_cn/memorydb/latest/devguide/images/concurrent-ex-conflict-data-types-last-writer-wins.png)


键 x 在区域 B 上创建为字符串类型，值为“b”。但在此之后，且在该操作复制到区域 A 之前，同一键在区域 A 上被创建为哈希类型。由于区域 A 的操作是最后执行的操作，该键最终将收敛为在区域 A 上创建的哈希。

**并发创建-删除：最后写入者胜出**

在同时删除和 “创建”（意思是 of 值） replacement/addition 的场景中，最后执行的操作将获胜。最终结果将由删除操作的顺序决定。如果删除操作先发生：

![并发创建-删除：如果删除操作先发生，则最后写入者胜出。](http://docs.aws.amazon.com/zh_cn/memorydb/latest/devguide/images/concurrent-create-delete-last-writer-wins-before.jpg)


区域 B 删除了 Set 类型的键 x。之后，区域 A 向该键添加了新成员。由于区域 A 的操作是最后执行的操作，该键最终将收敛为包含在区域 A 添加的唯一元素的 Set。

如果删除操作后发生：

![并发创建-删除：如果删除操作后发生，则最后写入者胜出。](http://docs.aws.amazon.com/zh_cn/memorydb/latest/devguide/images/concurrent-create-delete-last-writer-wins-after.jpg)


区域 A 向 Set 类型的键 x 添加了新成员。之后，该键在区域 B 被删除。由于区域 B 的操作是最后执行的操作，最终该键将被删除。

**计数器、并发操作：采用完整值复制与最后写入者胜出**

通过执行全值复制和应用，MemoryDB Multi-Region 中的计数器的行为与非计数器类型类似。 last-writer-strategy并发操作不会合并，而是最后一个操作将胜出。例如：

![如果最后写入者胜出，则采用完整值复制。](http://docs.aws.amazon.com/zh_cn/memorydb/latest/devguide/images/concurrent-full-rep-last-writer-wins.jpg)


在此场景中，键 x 的初始值为 1。然后区域 B 将计数器 x 增加 2，之后不久区域 A 将计数器增加 1。由于区域 A 的操作是最后执行的操作，并且增加 1 是最后执行的操作，键 x 最终将收敛为值 2。

**非确定性命令作为确定性命令复制**

为保证不同区域间值的一致性，在 MemoryDB 多区域中，非确定性命令作为确定性命令复制。非确定性命令是指那些依赖于外部因素的命令，例如 SETNX。SETNX 依赖于键是否存在，而该键可能存在于远程区域，但不存在于接收命令的本地区域。因此，原本非确定性的命令会作为完整值复制进行复制。对于字符串类型，它将作为 SET 命令复制。

![非确定性命令作为确定性命令复制。](http://docs.aws.amazon.com/zh_cn/memorydb/latest/devguide/images/nondeterministic_commands.png)


总之，所有对字符串类型的操作都作为 SET 或 DEL 复制；所有对哈希类型的操作都作为 HSET 或 HDEL 复制；所有对集合类型的操作都作为 SADD 或 SREM 复制；所有对有序集合的操作都作为 ZADD 或 ZREM 复制。