可伸缩架构(第2版):云环境下的高可用与风险管理
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

数据分区

数据分区的含义有很多种。在本节中,它表示将数据根据其中的某些键划分到不同的数据段中,通常为了利用多个数据库来存储更大规模的数据集合,或者获得比单个数据库更高的访问速度。

数据分区还有其他的类型(例如,之前提到的功能性分区),但是,在本节中,我们只关注基于键的数据分区策略。

举一个简单的数据分区示例,即将某个应用程序的所有数据按照账号进行分区。这样所有账户名称由A~D开头的数据被划分到一个数据库中,所有账户名称由E~K开头的数据被划分到另一个数据库中,以此类推(如图4-1所示)。[1]这是一个非常简单的例子,但是应用程序的开发人员通常会采用数据分区技术,来大幅提升可以访问应用程序的用户并发数量,同时支持更大规模的数据量。

图4-1:根据账户名称进行数据分区的示例

一般来说,你应当尽可能避免使用数据分区。为什么?因为一旦像这样对数据进行分区,就可能遇到以下这些问题。

应用程序复杂性

增加了应用程序的复杂性。因为从现在开始,你在实际获取数据之前,需要先去计算数据存放在哪里。

跨分区查询

无法很容易地获取多个分区中的数据。这一点在做业务数据分析查询时非常有用。

分区使用倾斜

需要很谨慎地选择建立分区所依赖的分区键。如果你选择了错误的键,那么就可能导致数据库分区使用不均衡,某些分区使用频繁而其他分区很少被使用,这样不仅会降低分区的有效性,同时也会增加数据库管理和维护的复杂性,如图4-2所示。

图4-2:账户超出数据分区能力的示例

重新分区

需要偶尔进行重分区来平衡分区之间的数据。根据选择的分区键和数据集合的类型、体量不同,重分区可能变得非常困难、非常危险(数据迁移),甚至在某些时候,几乎无法实现。

一般来说,账户名和账户ID都不是好的分区键(虽然它们经常被作为分区键使用)。这是因为一个账户的数据体量可能会发生变化。它开始时可能很小,适合分配在一个存放大量小账号的分区中。但是,如果随着时间推移,它变得越来越大,很快会因为单个分区无法承载压力,所以你不得不重新进行分区,来更好地平衡账户数据。如果一个账号变得太大,甚至超过单个分区的容量,就会导致整个分区方案失败,即使是重分区也无法解决这个问题。

更好的分区键应该是大小尽可能保持固定的键。分区数量增长应当尽可能保持独立和一致,如图4-3所示。如果需要重分区,应该是所有的分区都一致地增长,因为分区数据量太大以至于无法处理所以才重新分配分区。

图4-3:数据保持一致增长的分区示例

实际中可能会用到的分区方案是,选择一个会产生大量小元素的分区键,然后将这些小分区映射到一个更大的分区数据库中。以后如果需要重分区,只需更新映射关系,将个别小元素移动到新的分区中即可,这样就避免了对整个系统的大范围重分区。如何选择和使用适当的分区键本身就是一门艺术。