内容目录
Toggle序言
此篇 Data Replication 如何优化资料库? - 系统设计09 讲解了资料库复制的重要性,我们可以透过资料库复制的技巧,优化资料库。资料分区(Data Partitioning)则是另一个优化资料库很重要的概念,这一篇也会深入讲解资料库分区,并且分别讲解不同的分片方式(Database Sharding)。此篇文章的中文名称,包含资料分区、资料库分片,目前都是参照Azure 官方文件的翻译,不过还是建议读者使用原文称呼这些名词。
资料分区(Data Partitioning) 是什么?
资料分区(Data Partitioning) 是将资料库中的资料分割成更小、更易于管理的子区块的过程。这些子区块称为分区(Partition)。资料分割可以根据多种因素进行,例如:时间、客户ID 或产品类别。
为何我们要进行资料分区呢?
对于任何不对扩增的系统,资料量也会持续增长,并且针对资料库的读写流量也会越来越大,给传统资料库带来了可扩展性压力,因此我们可以使用资料分割,使我们能够使用多个节点,每个节点管理整个资料的一部分。
资料分区优点
- 提高性能:通过将资料分割成较小的部分,可以更轻松查询资料。这对于处理大量资料的系统尤很有帮助。
- 提高可扩展性:随着资料量的增加,可以轻松地添加更多分区来储存新资料,这可以让资料库可以持续扩展,而无需进行重大更改。
- 提高可用性:如果一个分区发生故障,则只有该分区中的资料会受到影响。其他分区仍可以继续使用,这有助于降低系统的整体停机时间。
- 简化管理:资料分区可以简化资料库的管理。例如:可以对每个分区单独备份和恢复,并且可以针对每个分区优化查询。
资料分区缺点
- 增加复杂性:资料分区会增加资料库的复杂性。需要开发和维护分割策略,并且系统可能需要进行一些更改用来适应分割的资料。
- 增加成本:资料分区可能需要额外的硬体和软体,并且管理分割的资料库的成本可能更高。
分片(Sharding)
为了在多个节点之间分配流量以及负载,我们需要透过分区(Partitioning)或分片(Sharding)来对资料进行分区。我们会将大型资料集合切分成较小的资料块,储存在不同节点上。
不过既然是要进行分割,就是必要让分区平衡,确保每个分区储存大约相同数量的资料。如果分区不平衡,大多数资料库查询落入少数分区,会造成负载过重的分区会不甘负荷,进而会造成系统瓶颈。另外,我们也会称这些乘载量过高的分区节点为热点(Hotspots)。
一般来说,我们会使用以下两种方式进行分片:垂直分片、水平分片
垂直分片(Vertical Sharding)
垂直分片(Vertical Sharding)是将不同的表格放在不同的资料库,这个方法可能运行在不同的伺服器上。这边我先提供其他官方文件的图例,让使用者可以更加明白其中的原理。
通常,垂直分片(Vertical Sharding)用来提高检索速度,例如:Blob 所组成的表(未来也会仔细介绍有关Blob 相关内容)。在这种情况下,具有大型文字资料或是Blob 的列,就会被拆分到不同的表中。
垂直分片(Vertical Sharding)适合手动分区,主要是因为这样的分片方式是相对复杂的,资料库管理者需要透过这些资料关联性,再来决定如何分区资料。相较之下,接下来要介绍的水平分片(Horizontal Sharding),即使在动态条件下也适合自动化。

水平分片(Horizontal Sharding)
除了前者介绍的垂直分片以外,还有另一种分片方式叫做水平分片(Horizontal Sharding)。如果资料库中,某些表(Table)太庞大并且会影响读取/写入效能的话,水平分片就是一个很好解决此问题的分片方式。
水平分片或分区是透过拆分资料将一张表分成多张表,并且也很好理解,假如有五百行的资料,则可以直接分成两个资料库,并且每一个资料库各有两百五十行。
我也附上图,让读者更了解水平分片的概念,通常我们有以下水平分片的方式,分别是:基于键的分片(Key Based Sharding)、基于范围的分片(Range Based Sharding) 、基于杂凑的分片(Hash Based Sharding),这些中文翻译是我参考腾讯技术文件的翻译,当然正常情况我们都会使用英文作为其称呼。

基于键的分片(Key Based Sharding)
基于键的分片(Key Based Sharding)是根据资料表中的键栏位将资料分割成多个分区的方法。例如:可以根据客户ID 将客户资料分割成多个分区,这样每个分区都包含特定客户的资料。
优点
使用基于键的分片(Key Based Sharding)方法,好处是查询效率很高,并且很容易实作出来,并且可以精确知道在哪里(哪个节点,哪个分片)寻找特定范围的键。
缺点
如果键的选择不是正确的话,由于流量分布不均匀,某些节点可能必须储存更多资料。简而言之,分片不均匀的可能性较高。

基于范围的分片(Range Based Sharding)
基于范围的分片(Range Based Sharding)是根据资料表中的某个范围栏位将资料分割成多个分区。例如:可以根据价格将商品资料分割成多个分区,这样每个分区都包含特定商品的资料。
优点
使用基于范围的分片(Range Based Sharding)好处是分片的平衡性较好,我们也可以单纯透过范围来决定要去查找哪一个资料库。
缺点
通常在查询范围较小的资料时,这样的资料分片方式是效率较低的。

基于杂凑的分片(Hash based sharding)
基于杂凑的分片(Hash based sharding)是根据资料表中的某个栏位的值对其进行杂凑(Hash Function),然后根据杂凑结果将资料分配到不同的分区。
优点
基于杂凑的分片(Hash based sharding)的优点是平衡性非常高,并且查询的效率也相对高。
缺点
可能存在热点问题,也复习一下前面提到的,如果分区不平衡,大多数资料库查询落入少数分区,会造成负载过重的分区会不甘负荷,进而会造成系统瓶颈。另外,我们也会称这些乘载量过高的分区节点为热点(Hotspots)。

重新平衡分割
当资料库查询负载本身是不平衡的时候,会造成资料库效能不佳,这时候我们需要去深入探究原因才有机会去修正问题,其中这些造成不平衡的原因可能包含:
- 资料的分布并不均匀。
- 单一分区上的负载过多。
- 查询流量增加,我们需要增加更多节点来负担系统流量。
以下是一些可以重新平衡分割的方法:
固定数量分区(Fixed number of partitions)
在这种方法中,一开始我们在设定资料库时,就建立固定的分区数量。正常情况,会建立比节点数量更多的分区,并将这些分区分配给节点。因此,当一个新节点加入系统时,它可以从现有节点中取出一些分区,直到这些分区被均分为止。
当然每个方法都有优、缺点。这种方法的缺点是,当每个分区的大小随着丛集(Cluster)中资料总量增加时,也会随之增长,因为所有分区只包含总资料的一小部分。另外,如果一个分区非常小,就会导致分区的成本过大,因为每个分区都会花费一些成本。如果分区非常大,重新平衡节点以及从节点故障中恢复的成本将会很高。选择正确的分区数量非常重要。
动态分区(Dynamic partitioning)
动态分区(Dynamic partitioning)中,当分区的大小达到设定的值时,原本的分区就会被平均分成两个分区。不同的分区,分配一个节点,最终,负载就会被平均分配。分区的数量会与总资料量动态的去平衡,这是动态分区的优点。
不过,动态分区有一个缺点。在同时进行资料库的读取以及写入时,很难动态重新平衡。读取和写入期间的动态重新平衡是很复杂的,因为读取与写入的资料,在不同节点上移动,如果这时候进行动态平衡,就会导致冲突甚至是延迟。为了确保资料一致性和可用性,就会带来复杂性,从而影响系统效能和可靠性。 MongoDB 就是使用这种动态分区知名的资料库之一。
如果尚不了解一致性、可用性、可靠性的读者,可以参考这一篇文章 软体设计非功能性特性– 系统设计03
请求路由(Request routing)
前面介绍了各种资料分区,不过在资料传进资料库之前,我们需要一个问题:当客户端在发出请求时,系统要如何知道要连接到哪个节点?重新平衡后,分区到节点的分配会改变。如果我们想要读取某个特定的资料库,我们如何知道需要连接哪个IP位址才能读取呢?这个问题也称为服务发现(Service Discovery)。以下是解决此问题的解法:
- 允许客户端请求网路中的任何节点。如果该节点不包含所请求的数据,则会将该请求转发到包含相关数据的节点。
- 建立一个路由层,将所有请求传送到路由层,再由路由层决定连接哪个节点来满足请求。
- 客户端已经拥有与分区相关的资讯以及哪个分区连接到哪个节点。因此,他们可以直接联系包含他们所需资料的节点。
ZooKeeper
如果要追踪分散式系统中,某一些丛集(Cluster)的修改,我们可以使用一些工具,其中一个知名的工具ZooKeeper,就可以做到以上的事情。 ZooKeeper 是Apache 为分散式系统提供的分散式开源协调服务。这个工具也可以,追踪网路中的所有映射(Mapping),每个节点都连接到ZooKeeper 以获取资讯。每当分区发生变化,或新增或删除节点时,ZooKeeper 就会更新并通知路由层有关变更的资讯。 ZooKeeper 被Yelp、RackSpace、Yahoo!、Reddit、Facebook 和Twitter 等公司使用。
结论
资料分区是一种将资料库中的资料分割成更小、更易于管理的子集的技术,可以提高资料库的性能、可扩展性、可用性和可管理性。
当资料库查询负载不平衡时,需要重新平衡分割以提高资料库性能。重新平衡分割的过程通常涉及识别不平衡的分割、制定重新平衡计划和执行重新平衡计划等步骤。
对于目前所有的分散式系统来说,分区已经成为标准,并且也是大部分软体工程师都需要知道的知识之一。也因为系统的资料量不断增加,因此对资料进行分区很有意义,它可以加快写入和读取速度,进一步提高系统的可用性、可扩展性和效能。
相关文章
Data Replication 如何优化资料库? - 系统设计09
系统设计元件介绍Building Block – 系统设计05
Back-of-the-envelope 封底计算– 系统设计04