# 10.8 数据分片（Protection Group）

这一部分讨论，Aurora如何处理大型数据库。目前为止，我们已经知道Aurora将自己的数据分布在6个副本上，每一个副本都是一个计算机，上面挂了1-2块磁盘。但是如果只是这样的话，我们不能拥有一个数据大小大于单个机器磁盘空间的数据库。因为虽然我们有6台机器，但是并没有为我们提供6倍的存储空间，每个机器存储的都是相同的数据。如果我使用的是SSD，我可以将数TB的数据存放于单台机器上，但是我不能将数百TB的数据存放于单台机器上。

为了能支持超过10TB数据的大型数据库。Amazon的做法是将数据库的数据，分割存储到多组存储服务器上，每一组都是6个副本，分割出来的每一份数据是10GB。所以，如果一个数据库需要20GB的数据，那么这个数据库会使用2个PG（Protection Group），其中一半的10GB数据在一个PG中，包含了6个存储服务器作为副本，另一半的10GB数据存储在另一个PG中，这个PG可能包含了不同的6个存储服务器作为副本。

![](https://2933519158-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MAkokVMtbC7djI1pgSw%2F-MFm4umOtKBcv00JRuuU%2F-MFmr5oD-Jro4r19gEdB%2Fimage.png?alt=media\&token=3752498e-bcc5-4955-a9c3-5321f8994939)

因为Amazon运行了大量的存储服务器，这些服务器一起被所有的Aurora用户所使用。两组PG可能使用相同的6个存储服务器，但是通常来说是完全不同的两组存储服务器。随着数据库变大，我们可以有更多的Protection Group。

这里有一件有意思的事情，你可以将磁盘中的data page分割到多个独立的PG中，比如说奇数号的page存在PG1，偶数号的page存在PG2。如果可以根据data page做sharding，那是极好的。

Sharding之后，Log该如何处理就不是那么直观了。如果有多个Protection Group，该如何分割Log呢？答案是，当Aurora需要发送一个Log条目时，它会查看Log所修改的数据，并找到存储了这个数据的Protection Group，并把Log条目只发送给这个Protection Group对应的6个存储服务器。这意味着，每个Protection Group只存储了部分data page和所有与这些data page关联的Log条目。所以每个Protection Group存储了所有data page的一个子集，以及这些data page相关的Log条目。

如果其中一个存储服务器挂了，我们期望尽可能快的用一个新的副本替代它。因为如果4个副本挂了，我们将不再拥有Read Quorum，我们也因此不能创建一个新的副本。所以我们想要在一个副本挂了以后，尽可能快的生成一个新的副本。表面上看，每个存储服务器存放了某个数据库的某个某个Protection Group对应的10GB数据，但实际上每个存储服务器可能有1-2块几TB的磁盘，上面存储了属于数百个Aurora实例的10GB数据块。所以在存储服务器上，可能总共会有10TB的数据，当它故障时，它带走的不仅是一个数据库的10GB数据，同时也带走了其他数百个数据库的10GB数据。所以生成的新副本，不是仅仅要恢复一个数据库的10GB数据，而是要恢复存储在原来服务器上的整个10TB的数据。我们来做一个算术，如果网卡是10Gb/S，通过网络传输10TB的数据需要8000秒。这个时间太长了，我们不想只是坐在那里等着传输。所以我们不想要有这样一种重建副本的策略：找到另一台存储服务器，通过网络拷贝上面所有的内容到新的副本中。我们需要的是一种快的多的策略。

Aurora实际使用的策略是，对于一个特定的存储服务器，它存储了许多Protection Group对应的10GB的数据块。对于Protection Group A，它的其他副本是5个服务器。

![](https://2933519158-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MAkokVMtbC7djI1pgSw%2F-MFm4umOtKBcv00JRuuU%2F-MFn1VqYEoXl67v9IZ6M%2Fimage.png?alt=media\&token=50eeb3d0-7ea6-42c3-94dd-dd6e0ae0b38d)

或许这个存储服务器还为Protection Group B保存了数据，但是B的其他副本存在于与A没有交集的其他5个服务器中（虽然图中只画了4个）。

![](https://2933519158-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MAkokVMtbC7djI1pgSw%2F-MFm4umOtKBcv00JRuuU%2F-MFn1uGMcIvwLKSR0obe%2Fimage.png?alt=media\&token=73359271-00bd-426b-832b-9647e82783f8)

类似的，对于所有的Protection Group对应的数据块，都会有类似的副本。这种模式下，如果一个存储服务器挂了，假设上面有100个数据块，现在的替换策略是：找到100个不同的存储服务器，其中的每一个会被分配一个数据块，也就是说这100个存储服务器，每一个都会加入到一个新的Protection Group中。所以相当于，每一个存储服务器只需要负责恢复10GB的数据。所以在创建新副本的时候，我们有了100个存储服务器（下图中下面那5个空白的）。

![](https://2933519158-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MAkokVMtbC7djI1pgSw%2F-MFm4umOtKBcv00JRuuU%2F-MFn6neq6Rc5VapzQF40%2Fimage.png?alt=media\&token=8565a162-47f5-4f4b-b893-613aa8aad366)

对于每一个数据块，我们会从Protection Group中挑选一个副本，作为数据拷贝的源。这样，对于100个数据块，相当于有了100个数据拷贝的源。之后，就可以并行的通过网络将100个数据块从100个源拷贝到100个目的。

![](https://2933519158-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MAkokVMtbC7djI1pgSw%2F-MFm4umOtKBcv00JRuuU%2F-MFn8TpF_c-WT8Do98vl%2Fimage.png?alt=media\&token=f54dad40-d4ab-4952-b572-6fa547b42e47)

假设有足够多的服务器，这里的服务器大概率不会有重合，同时假设我们有足够的带宽，现在我们可以以100的并发，并行的拷贝1TB的数据，这只需要10秒左右。如果只在两个服务器之间拷贝，正常拷贝1TB数据需要1000秒左右。

这就是Aurora使用的副本恢复策略，它意味着，如果一个服务器挂了，它可以并行的，快速的在数百台服务器上恢复。如果大量的服务器挂了，可能不能正常工作，但是如果只有一个服务器挂了，Aurora可以非常快的重新生成副本。
