随着互联网时代,尤其是移动互联网时代的到来,各类企业在向互联网转型的过程中,都在快速升级迭代自己的系统平台。在此背景下,这类应用平台所依赖的数据库系统需要支持突然增加的庞大交易数据,但在这种情况下,单体数据库往往会很快过载,扩容数据库最常见的技术手段是“数据分片”。所以今天我将向您介绍什么是分片以及如何使用它来扩展您的数据库。同时,我也会回顾一下常见的分片架构的优缺点,并以TiDB为例和大家一起探讨如何在分布式数据库中实现分片。数据分片概述分片是将一个大数据表分解成更小的表(称为分片)的过程,这些表分布在多个数据库集群节点上。分片本质上可以看作是传统数据库中的分区表,是一种横向扩展的手段。每个分片包含原始总数据集的一个子集,因此总负载可以在分区之间分配。数据分片一般有两种方式。水平分片:将同一张表的不同行存储在不同的数据库节点中。垂直分片:不同的表列存储在不同的数据库节点中。如下图所示,水平和垂直这两个概念来自于对原始关系数据库表模式的直观视图。图1可视化和直观视图分片的概念实际上来源于经济学的边际收益理论:如果投资继续增加,但增加的收益开始下降,称为边际收益递减的状态。而它刚开始下降的点称为边际均衡点。该理论在数据库计算能力上的应用常表现为:如果数据库处理能力遇到瓶颈,最简单的方法就是不断提升系统性能,比如更换更强大的CPU、更大的内存等,这种模式就是称为垂直扩展。随着资源不断增加以增加数据库容量,垂直扩展有其自身的局限性,最终达到边际平衡和收益递减。这时表的水平分片意味着可以引入更多的算力来处理数据和交易。因此,将利润率递减的状态逆转为边际增长。同时,通过不断均衡所有节点上的处理负载和数据量,分片模式还可以达到1+1>2的效果,即集群的平均处理能力大于单个节点。这使得由更小、更便宜的服务器组成的水平可扩展集群可能比维护大型商品数据库服务器更具成本效益。这也是第一讲“De-IOEMovement”的核心技术背景。除了解决扩展挑战外,分片还可以减少计划外停机并大大减少系统RTO(恢复时间目标)。即使在计划停机期间,没有分片的加持,整个数据库仍然无法访问,无法满足业务对SLO(目标服务水平)的要求。如果分片按照我们想要的方式工作,它可以确保系统的高可用性。即使数据库集群的某些节点出现故障,只要其他节点在其中运行,整个数据库仍然可以对外提供服务。当然这也需要复制和一致性服务的保证,这个我们会在后面的讲义中进一步讨论。总而言之,分片可以增加数据库集群的整体容量并加快处理速度,同时以比垂直扩展更低的成本提供更高的可用性。分片算法分片算法一般是指水平分片所需要的算法。经过多年的演进,在大型系统中得到了广泛的应用。下面我将介绍两种最常见的水平分片算法,并简单介绍一些其他的分片算法优化思路。HashshardingHashsharding首先需要获取shardkey,然后根据特定的hash算法计算出它的hash值,最后根据hash值来决定数据应该放在哪个shard上。数据库一般使用统一的hash算法(比如asketama)为所有数据提供哈希函数,以方便数据在服务器之间均匀分布,从而降低因数据不平衡导致的热点风险。使用这种方法,数据不太可能放在同一个分片上,从而导致数据随机分布。该算法非常适合随机读写场景,可以很好的分散系统负载,但缺点是不利于范围扫描查询操作。下图显示了该算法的工作原理。RangeshardingRangesharding根据数据值或key空间的范围来划分数据,相邻的shardkey更有可能落在同一个shard上。每行数据不需要像哈希分片那样进行转换,实际上只是简单地归类到不同的分片中。下图显示了范围分片的工作原理。范围分片需要选择合适的分片键,这些分片键应尽量不包含重复值,即它们的候选值应尽可能离散。同时,数据不能单调递增或单调递减,否则数据不能很好地分散在集群中,造成热点。范围分片非常适合范围查找,但随机读写性能较弱。FusionAlgorithm在这一点上我们应该意识到上面介绍的散列和范围分片算法不是非此即彼的。相反,我们可以灵活地组合它们。例如,我们可以构建一个多级分片策略,在顶层使用哈希算法,在每个基于哈希的分片单元中,数据将被顺序存储。该算法比较简单灵活。接下来说说一个地理位置算法。地理位置算法这种算法一般用在NewSQL数据库中,提供全球分布数据的能力。在基于地理位置的分片算法中,数据被映射到特定的分片,这些分片又被映射到特定的区域和这些区域中的节点。在给定区域内,然后使用哈希或范围分片对数据进行分片。例如,运行在美国、中国、日本3个区域的集群,可以依赖User表的Country_Code列,将特定用户(User)的数据行映射到满足位置邻近规则的区域。所以以上就是几种典型的分片算法。接下来,我们将讨论如何将分片算法应用到实际场景中。Manualshardingvsautomaticsharding手动分片,顾名思义,就是设置静态规则,按照分片算法将数据分发到数据库节点。这一般是因为用户使用的数据库不支持自动分片,如MySQL、Oracle等,这个问题可以通过应用层面的数据分片来解决,也可以通过简单的数据库中间件或代理设置静态分片规则来解决.手动分片的缺点是数据分布不均匀。数据分布不均会导致数据库负载极度不平衡,使某些节点过载而其他节点接收的流量较少。因此,最好避免在某些节点上存储过多的数据,否则这些节点会成为访问热点,从而减慢其运行速度,甚至导致服务器崩溃。另外,当整体数据集太小的时候,也会导致这个问题,因为集群中只有部分节点有数据。这在开发和测试环境中是可以接受的,但在生产环境中是不可接受的。由于数据分布不均,存在热点,数据存储在过少的分片上,会导致数据库集群中节点的计算资源耗尽,导致系统不稳定。但如果精心设计,数据分布变化不大,手动分片也是一种相对简单、低维护的方案。使用自动分片意味着计算节点和分片算法可以相互配合,使数据库可以弹性扩展。使用基于范围的分片,自动分片很容易:只需拆分或合并每个分片。假设有一个范围为[1,100)的分片,我们要将其拆分为两个范围,首先选择50作为拆分点;然后将区域划分为[1,50)和[50,100),将两个区域移动到两个不同的数据库节点以平衡系统负载。基于范围的分片可以引入读写热点,我们可以通过拆分和移动分片来消除这些热点。对于使用基于散列的分片的系统来说,自动分片是昂贵的。我们现在用上面图1中的例子来说明。当前系统有4个节点,然后添加一个新的数据库节点。在哈希函数中,“n”从4变为5,导致系统抖动较大。虽然你可以使用像Ketama这样的一致性哈希算法来最小化系统抖动,但数据迁移和重新平衡操作仍然是必要的。这是因为应用哈希函数后,数据是随机分布的,调整哈希算法肯定会改变大部分数据的分布。自动分片是分布式数据库的主流功能。所有主要的分布式数据库甚至数据库中间件都在尝试自动分片。下面我将结合几个案例来说明。分片算法案例数据分片是数据库中间件的核心功能,这方面的开源项目很多。这里我将以ApacheShardingShpere的分片内容为例,向大家介绍分片算法的相关实战案例。Shardingkey生成ShardingShpere首先提供分布式主键生成,这是生成shardingkey的关键。由于分布式数据库通常涉及多个数据库节点,基于数据库实例生成主键不适合分布式场景。常用的算法有UUID和Snowfalke两种无状态生成算法。UUID是最简单的方式,但是生成效率不高,数据分散度一般。因此,目前生产环境采用的是后一种算法。下图是该算法生成的shardkey的结构。图4中的shardkey结构中有3个有效部分。使用了将近70年。工作节点ID:保证每个独立工作的数据库节点不会产生重复的数据。访问顺序:同一进程,同一毫秒内,保证生成的ID不重复。灵活的分片算法为了保证分片计算的灵活性,ShardingShpere提供了标准的分片算法和一些工具来帮助用户实现个性化的算法。PreciseShardingAlgorithm可以与哈希函数一起使用来实现哈希分片。RangeShardingAlogrithm可以实现范围分片。使用ComplexShardingStrategy可以使用多个分片键来实现融合分片算法。有时,数据表的分片方式并不完全一致。对于一些特殊的分片模式,可以使用HintShardingStrategy在运行状态下制定特殊的路由规则,而不是使用统一的分片配置。如果用户想实现特殊的分片算法,比如地理位置算法,可以自定义分片策略。使用内联表达式或Java代码编写。前者不需要基于配置的编译,适用于简单的个性化分片计算;后者可以实现更复杂的计算,但需要编译打包的过程。用户可以通过以上多种分片工具灵活、统一地制定数据库分片策略。自动分片ShardingShpere提供了Sharding-Scale来支持数据库节点的弹性伸缩,也就是它对自动分片的支持。下图是自动分片功能的展示。可以看到,Sharding-Scale特性进行扩容后,原来的两个数据库扩容为三个。图5显示了自动分片功能。自动分片由四个过程组成,如下图所示。图6自动分片流程从图6可以看出,通过这个工作负载,ShardingShpere可以支持复杂的基于哈希的自动分片。同时,我们也应该看到,如果没有专业的、自动化的弹性伸缩工具,自动化分片是很难实现的。以上是分片算法的实际案例,采用了经典的水平分片模式。目前,水平分片和垂直分片有进一步融合的趋势,下面要介绍的TiDB就代表了这种融合趋势。纵横分片整合案例TiDB是纵横分片整合的典型案例,本方案也是一种HATP整合方案。横向扩展依赖于底层的TiKV,如下图所示。图7TiKVTiKV采用rangesharding的方式,将数据分配到Region组中。一个组维护三副本,保证了高可用(相关内容将在《05|一致性与CAP模型:为什么需要分布式一致性?》中详细介绍)。当Region变大时,它会被分裂,新分裂的Region也会产生多个副本。TiDB的水平扩展依赖于TiFlash,如下图所示。图8TiFlash从图8可以看出,TiFlash是TiKV的一个列扩展插件。数据从TiKV异步复制到TiFlash,然后进行列转换。使用MVCC技术来保证数据的一致性。上面提到的Region会新增一个异步副本,然后将副本拆分成数据,以列的方式组合到TiFlash中,从而实现同一个数据库中横向和纵向的一体化扩展。这是两个数据库引擎的融合。以上集成给TiDB带来的好处主要体现在查询层面,尤其是对特定列的聚合查询效率非常高。TiDB可以在以上两种分片引擎之间进行智能切换,以达到最优的查询效率。小结今天首先详细介绍了分片的原理,以及各种常用的分片技术;然后分析了手动分片和自动分片的区别,知道数据分片的未来属于自动分片。最后通过两个著名的开源项目介绍了分片技术是如何应用于分布式数据库的。其中,TiDB展示的HATP融合两种分片模式的技术路线,可以看作是未来分片模式的发展趋势。
