什么是分片?

分片(Sharding)是一种与水平切分(horizontal partitioning)相关的数据库架构模式——将一个表里面的行,分成多个不同的表的做法(称为分区)。每个区都具有相同的模式和列,但每个表有完全不同的行。同样,每个分区中保存的数据都是唯一的,并且与其他分区中保存的数据无关。

从水平切分(horizontal partitioning)与垂直切分(vertical partitioning)的关系,可能会有所帮助。在垂直切分表中,所有的列被分离出来,并放入新的不同的表中。每个垂直切分内的数据,独立于所有其他分区中的数据,并且每个分区都包含不同的行和列。下图说明了如何在水平和垂直方向上对表进行分区:

 

数据库分片_数据

 

range 分区是一种水平分区。

分片(Sharding)将一个数据分成两个或多个较小的块,称为逻辑分片(logical shards)。然后,逻辑分片(logical shards)分布在单独的数据库节点上,称为物理分片(physical shards)。物理分片(physical shards)可以容纳多个逻辑分片(logical shards)??。

数据库分片(Database shards)是无共享架构的一个例子。这意味着分片是自治的:分片间不共享任何相同的数据或服务器资源。

通常,分片(Sharding)在应用程序级别进行实现。这意味着应用程序包含“要向哪个分片发送读和写”的代码。但是,某些数据库管理系统内置了分片功能,允许您直接在数据库级别实现分片。

分片的优点

数据库分片的主要吸引力在于,它可以帮助促进水平扩展(horizontal scaling),也称为向外扩展(scaling out)。水平扩展是将更多的机器添加到现有堆栈中,以分散负载,允许更多的流量和更快的处理。这通常与垂直扩展(vertical scaling)形成对比,垂直扩展也称为向上扩展(scaling up),是指升级现有服务器的硬件,通常是添加更多内存或CPU。

分片的缺点

要考虑的最后一个缺点是,并不是每个数据库引擎本身都支持分片。例如,尽管可以手动分片PostgreSQL数据库,但PostgreSQL本身并不包括自动分片功能。有许多Postgres分支包括自动分片功能,但这些分支通常落后于最新的PostgreSQL版本,并且缺乏某些其他的功能特性。一些专业的数据库技术——如MySQL Cluster或某些数据库即服务产品(如MongoDB Atlas)确实包含自动分片功能,但这些数据库管理系统的普通版本却并不包含。因此,分片通常需要“自己动手”的方法。这意味着通常很难找到有关分片或故障排除技巧的文档。

分片架构

基于键值的分片

 

数据库分片_数据库_02

 

基于范围的分片

基于范围的分片(Range based sharding),基于给定值的范围进行数据分片。为了说明,假设您有一个数据库,用于存储零售商目录中所有产品的信息。您可以创建一些不同的分片,并根据每个产品的价格范围分配每个产品的信息,如下所示:

 

数据库分片_数据库_03

 


本案例中基于第二列 Price 进行范围划分得到分片

基于目录的分片

要实现基于目录的分片,必须创建并维护一个使用分片键的查找表,以跟踪哪个分片保存哪些数据。简而言之,查找表是一个表,其中包含一组静态信息,这些信息描述可以在何处找到特定数据。下图显示了基于目录分片的简化示例:


 

数据库分片_数据_04

 

此处,“ 交付区”列定义为分片键。分片键中的数据与每行应写入的分片一起被写入查找表。这类似于基于范围的分片,但不是确定分片密钥的数据属于哪个范围,而是将每个密钥绑定到其自己的特定分片。如果分片密钥的基数较低,并且分片存储一定范围的密钥没有意义,那么基于目录分片是基于范围分片的不错选择。注意,它也与基于密钥的分片不同,因为它不通过哈希函数处理分片密钥。它只是对照查找表检查密钥,以查看需要将数据写入何处。

基于目录分片的主要优势在于它的灵活性。基于范围分片将限制为指定值的范围,而基于键的分片将限制为使用固定的哈希函数,(此哈希函数以后很难更改)。而基于目录分片允许使用任何系统算法为分片分配数据条目,并且使用此方法动态添加分片相对容易。

尽管基于目录分片是此处讨论最灵活的分片方法,但是在每次查询或写入之前,连接到查找表的需求可能会对应用程序的性能产生不利影响。此外,查找表可能会成为单点故障:如果它损坏或以其他方式失败,则会影响写入新数据或访问其现有数据。

我应该分片吗?

是否应该实施分片数据库是一个辩证的问题。有些人认为分片是达到一定规模的数据库的必然结果,而另一些人则认为这是令人头痛的事情,除非绝对必要,否则应该避免,因为分片会增加操作的复杂性。

由于增加了复杂性,因此通常仅在处理大量数据时才执行分片。以下是一些常见的场景,在这些场景中分片数据库可能会有所帮助:

· 应用程序数据量增长到超过单个数据库节点的存储容量。

· 对数据库的写或读量超过单个节点或其只读副本可以处理的量,导致响应时间变慢或超时。

· 应用程序所需的网络带宽超过了单个数据库节点和任何只读副本可用的带宽,导致响应时间变慢或超时。

在分片之前,应该用尽所有其他方式来优化数据库。您可能要考虑的一些优化包括:

· 建立一个远程数据库。如果您正在使用其所有组件都位于同一服务器上的整体应用程序,则可以通过将数据库移至其自己的计算机上来提高数据库的性能。由于数据库表保持完好无损,所以这不会像分片那样增加复杂性。但是,它仍然允许您与其他基础架构分开纵向扩展数据库。

· 实现缓存。如果您的应用程序的读取性能是造成您麻烦的原因,那么缓存是可以帮助改进它的一种策略。缓存涉及将已经请求的数据临时存储在内存中,从而使您以后可以更快地访问它。

· 创建一个或多个只读副本。可以帮助提高读取性能的另一种策略是,将数据从一个数据库服务器(主服务器)复制到一个或多个辅助服务器上。此后,每个新的写操作都会先复制到主服务器上,然后再复制到辅助服务器上,而读操作将仅对辅助服务器进行。像这样分布读写,可以防止任何一台计算机承担过多的负载,从而有助于防止速度下降和崩溃。请注意,创建只读副本会涉及更多的计算资源,因此会花费更多的金钱,这对于某些人而言可能是一个重大限制。

· 升级服务器硬件。在大多数情况下,将数据库服务器升级更多资源比分片需要更少的工作。与创建只读副本一样,具有更多资源的服务器可能会花费更多资金。因此,只有在真正成为最佳选择的情况下,才应调整大小。

请记住,如果您的应用程序或网站增长到一定程度,这些策略都不足以满足性能需求。这时候,分片可能确实是您的最佳选择。

结论

对于希望水平扩展数据库的用户来说,分片是一个很好的解决方案。但是,这也增加了很多复杂性,并为您的应用程序创建了更多潜在的故障点。某些人可能需要分片,但是创建和维护分片架构所需的时间和资源可能会超过其他人的利益。

通过阅读本文,您应该对分片的利弊有更清晰的了解。接下来,您可以利用这种见解来做出更明智的决定,以了解分布式数据库是否适合您的应用程序。


原文:https://www.digitalocean.com/community/tutorials/understanding-database-sharding

参考:

  1. https://zhuanlan.zhihu.com/p/98355383
  2. https://zhuanlan.zhihu.com/p/99017933



作者:无玄

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。