数据分区基本概念

数据分区是分布式数据库非常重要的一个概念,本文主要整理 DDIA Chapter 6 和一些介绍数据分区的博客。

什么是数据分区

本小节内容直接截取于我认为概括地简洁清晰的一篇博客:https://iswade.github.io/articles/partition/

分布式数据处理系统第一个要解决的问题就是如何将数据进行拆分,利用多台计算机处理大规模数据。对于数据量很大的数据集,单机无法保存或者处理时,通过对数据集进行水平拆分,将不同的数据子集存放到不同的处理节点,这种对数据进行拆分的方式叫做 分区(partition)

不同数据库中对分区的名称定义有所差异,有些称之为分区(partition),有些称之为分片(sharding),还有一些称之为区域(Region),但是其含义都是基本相同的。需要注意的是,这里的分区跟 CAP 中的网络分区和单机的单机分区表没有关系。

对于大部分实现方案,数据被分区后,各个分区由不同的独立、完整的数据库进行保存和处理,然后由一个或多个协调节点进行请求的路由处理。基本结构如下图所示:

  • CN: 协调节点(coordinator node),根据分区策略对数据做分区处理。
  • DN: 数据节点(data node),用于保存数据,独立维护自己的元数据,通常都是完整的数据库,每个 DN 保存一个数据子集,每个数据子集都是一个分区。

通常情况下,对 SQL 数据库、KV 数据库进行分区的处理策略类似,每条记录数据、一个键值对保存在一个分区中(通常情况下,每条数据属于且仅属于⼀个分区),分区策略定义了对每条数据的处理方式,SQL 数据集库一般在建表时通过 SQL 语法指定分区策略,KV 数据库一般是数据库内部进行分区,数据库多个分区进行操作时,对应用通常是透明的。

在无共享架构下,对大数据集进行分区处理是当前分布式数据处理系统最常见处理方式。分区主要是为了提升系统的 可扩展性,读写负载都可以随着分区的增加而扩展。不同的分区可以放在无共享集群中的不同节点上。因此,大数据集可以分布在多个磁盘上,并且查询负载可以分布在多个处理器上。

对于在单个分区上运行的查询,每个节点可以独立执行对自己分区的查询,因此可以通过添加更多的节点来扩大查询吞吐量。复杂的查询可能会跨越多个节点并行处理。

分区策略

分区⽬标是将数据和查询负载均匀分布在各个节点上。如果每个节点公平分享数据和负载,那么理论上 10 个节点应该能够处理 10 倍的数据量和 10 倍的单个节点的读写吞吐量(不考虑复制)。

如果分区是不公平的,⼀些分区⽐其他分区有更多的数据或查询,称之为 偏斜(skew)。数据偏斜的存在使分区效率下降很多。在极端的情况下,所有的负载可能压在⼀个分区上,其余 9 个节点是空闲的,瓶颈落在这⼀个繁忙的节点上。不均衡导致的⾼负载的分区被称为 热点(hot spot)。理论上,我们应该尽量避免出现数据偏斜。

对于一个分布式数据处理系统,将数据分布到多个分区有两种比较典型的方案:

  1. 范围分区,某一段连续的键都保存在一个数据节点上。
  2. 根据键做哈希,根据哈希值选择对应的数据节点。

范围分区

⼀种分区的⽅法是为每个分区指定⼀块连续的键范围(从最⼩值到最⼤值),如纸质百科全书的卷。如果知道范围之间的边界,则可以轻松确定哪个分区包含某个值。如果你还知道分区所在的节点,那么可以直接向相应的节点发出请求。

键的范围不⼀定均匀分布,因为数据也很可能不均匀分布。例如上图中,第 1 卷包含以 A 和 B 开头的单词,但第 12 卷则包含以 T、U、V、X、Y 和 Z 开头的单词。只是简单的规定每个卷包含两个字⺟会导致⼀些卷⽐其他卷⼤。为了均匀分配数据,分区边界需要依据数据调整

在每个分区中,我们可以按照⼀定的顺序保存键,这样进行范围扫描⾮常简单。不过,范围分区在某些特定的访问模式下会导致热点。 如果主键是时间戳,则分区对应于时间范围,例如,给每天分配⼀个分区。 不幸的是,由于我们在测量发⽣时将数据从传感器写⼊数据库,因此所有写⼊操作会转到同⼀个分区(即今天的分区),这样分区可能会因写⼊⽽过载,⽽其他分区则处于空闲状态。

为了避免传感器数据库中的这个问题,需要使⽤除了时间戳以外的其他东⻄作为主键的第⼀个部分。 例如,可以在每个时间戳前添加传感器名称,这样会⾸先按传感器名称,然后按时间进⾏分区。 假设有多个传感器同时运⾏,写⼊负载将最终均匀分布在不同分区上。 现在,当想要在⼀个时间范围内获取多个传感器的值时,你需要为每个传感器名称执⾏⼀个单独的范围查询。

散列分区

由于偏斜和热点的⻛险,许多分布式数据存储使⽤散列函数来确定给定键的分区。

出于分区的⽬的,散列函数不需要多么强壮的加密算法,我们更需要关注的是其是否可以将数据均匀分布。⼀旦找到⼀个合适的键散列函数,我们可以为每个分区分配⼀个散列范围(⽽不是键的范围),每个通过哈希散列落在分区范围内的键将被存储在该分区中,如下图所示:

散列分区保存的元数据很简单,只需要保存桶与分区的映射关系即可,并且散列分区通常能够实现数据在各个分区之间的均匀分布。

不过,使用散列分区时,选择合适的散列函数非常重要,如果使用的散列函数导致数据分布不均,可能会引发数据倾斜和性能瓶颈。并且,在使⽤键散列进⾏分区时我们失去了键范围分区的⼀个很好的属性:⾼效执⾏范围查询的能⼒。曾经相邻的键现在分散在所有分区中,所以它们之间的顺序就丢失了。使用散列分区时,如果需要调整分区数量(例如,由于数据量的增长或节点的增减),可能需要重新散列数据,这可能导致昂贵的数据迁移和重新分布操作。

分区再平衡

随着时间的推移,数据库会有各种变化:

  • 查询吞吐量增加,所以你想要添加更多的 CPU 来处理负载。
  • 数据集⼤⼩增加,所以你想添加更多的磁盘和 RAM 来存储它。
  • 机器出现故障,其他机器需要接管故障机器的责任。

所有这些更改都需要数据和请求从⼀个节点移动到另⼀个节点。 将负载从集群中的⼀个节点向另⼀个节点移动的过程称为 再平衡(rebalancing)

⽆论使⽤哪种分区⽅案,再平衡通常都要满⾜⼀些最低要求:

  • 再平衡之后,负载(数据存储,读取和写⼊请求)应该在集群中的节点之间公平地共享。
  • 再平衡发⽣时,数据库应该继续接受读取和写⼊。
  • 节点之间只移动必须的数据,以便快速再平衡,并减少⽹络和磁盘 I/O 负载。

参考

  1. https://iswade.github.io/articles/partition/
  2. DDIA Chapter 6
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值