用“分区”来面对超大数据集和超大吞吐量

京东云开发者
• 阅读 0

1. 为什么要分区?

分区(partitions) 也被称为 分片(sharding) ,通常采用对数据进行分区的方式来增加系统的 可伸缩性,以此来面对非常大的数据集或非常高的吞吐量,避免出现热点。

分区通常和复制结合使用,使得每个分区的副本存储在多个节点上,保证数据副本的 高可用。如下图所示,如果数据库被分区,每个分区都有一个主库。不同分区的主库可能在不同的节点上,每个节点可能是某些分区的主库,同时是其他分区的从库。

用“分区”来面对超大数据集和超大吞吐量

1.1 一致前缀读

分区也会由于复制延迟而产生问题,我们先来看下图中的例子,是Poons先生和Cake小姐的对话:

用“分区”来面对超大数据集和超大吞吐量

Poons先生先问: “How far into the future can you see, Mrs.Cake?”

Cake小姐回答说: “About ten seconds usually, Mr.Poons.”

正常情况下,这段对话是有因果关系的(先问后答)。但是对于观察者,他看到的顺序却是先得到了答案,再看到了问题,这就是在分区数据库中,因复制延迟而产生的特殊情况。

为了避免这种混乱,我们就需要保证 一致前缀读:如果一系列写入按某个顺序发生,那么任何人读取这些写入时,也会看见它们以同样的顺序出现。一种解决方案是,确保任何因果相关的写入都在相同的分区。

2. 该怎么分区?

分区的目的是将数据和负载均匀的分布到各个节点上,理论上10个节点能够处理10倍的数据量和10倍单节点的读写吞吐量。

但是如果分区不均,那么就会出现一些分区有更多的数据或读写,我们称之为 偏斜,这会使得分区后并没有得到很大的效率提升。在极端情况下,所有的负载如果都落在一个分区,使得该分区负载过高,我们称之为 热点

所以,为了避免偏斜和热点的产生,以键值数据的分区为例,讨论如何将数据分区做得妥当。

2.1 根据键的范围进行分区

我们可以根据键值的范围进行分区,比如说我们以26个英文字符划分26个分区,之后根据键值首字母对它们进行分区。通常情况下,键值并不是均匀分布的,这会造成按照首字母分区之后,发生数据偏斜。为了均匀分配数据,分区的边界需要根据数据分区的实际情况再进行调整。

2.2 散列分区

一个好的散列函数可以将数据均匀分布,避免发生偏斜。但是这也带来了问题:我们没有办法再进行高效的范围查询。

3. 热点消除

避免热点最简单的方法是将数据记录进行散列分区,记录因此会在所有节点上平均分配。

但是它并不能完全避免热点的产生,因为如果所有的读写操作都是针对同一个键的话,那么所有的请求还是会被路由到同一个分区。比如说有一个百万粉丝的博主发布动态,该动态根据博主ID的键值进行分区,如果此时有大量的粉丝对该动态进行互动,那么哈希策略会把这些请求都路由到同一个分区进行操作,发生热点事件。

其实,我们还可以在该热点键上再进行分区,以避免热点:在主键的最后拼接随机数,两位十进制的随机数就能把一个主键分成100个不同的主键,从而存储在不同的分区中,这就完成了热点消除。但是主键被分割后,任何读取工作都必须在每次读取时将所有的数据拉出去合并到一起再返回结果。

4. 分区再平衡

如果保存某分区数据的服务器故障,需要使用其他服务器接管或想将目前的服务器换成性能更好的服务器,那么就需要进行 分区再平衡

分区再平衡 是将负载从集群中的一个节点向另一个节点移动的过程。执行再平衡需要满足以下要求:

  • 再平衡期间,数据库应该继续接受读取和写入
  • 节点之间只移动必须的数据,以便快速再平衡,并减少网络和磁盘的IO负载
  • 再平衡之后,负载应该在集群中的节点之间公平地共享

比较简单的再平衡分区策略是选择 固定数量的分区,当节点数量增加时,可以从原节点中 窃取 一些分区(当节点数量减少时,则发生相反的情况),如下图所示:

用“分区”来面对超大数据集和超大吞吐量

在这种配置中,分区的数量通常在数据库第一次建立时确定,操作比较简单,之后不会改变,因此你需要选择足够多的分区以适应未来的增长。但是,每个分区也有管理开销,所以选择太大的数字会适得其反。

除此之外也可选择 动态分区,根据配置的分区大小,当超过该阈值时,可以将该大分区分割成两个小分区,能够使 分区数量适应总数据量。在大型分区拆分后,可以将其中的一半转移到另一个节点上,以平衡负载。

还有一种 根据节点数增加来进行分区 的方法:每个节点上有固定的分区数,当节点增加时,分区将变小,新增的节点会从原有节点的分区中随机进行拆分,最终这个新节点获得公平的负载份额。

分区再平衡可以 手动执行 也可以 自动执行。自动再平衡比较方便,因为不需要人工维护,但是它的执行过程是不可预测的:再平衡时将大量数据集从一个节点转移到另一个节点的过程中可能会产生很大的网络开销,这会使得该服务器对请求响应的性能降低,对用户的体验和生产造成负面影响。所以再平衡的过程有人参与是一件好事,这样能防止发生运维问题。

5. 请求路由(服务发现)

当我们已经将数据进行分区后,如何才能知道用户想要的数据在哪个节点上?这可以概括为是一个 服务发现 的问题。为了解决这个问题,可以通过如下图所示的三个方案

用“分区”来面对超大数据集和超大吞吐量

  1. 允许访问所有的节点,如果第一个访问的节点有该键值,则处理该请求,否则将该请求转发到适当的节点上,这个方法避免了使用注册中心中间件,但是实现比较复杂
  2. 使用分布式的协调服务,用户将所有的请求发送到路由层,由路由层将该请求转发到合适的节点
  3. 要求用户(客户端)自己知道分区和节点的分配

但是这其中还隐藏着一个问题:作出决策的组件(节点之一、路由层或客户端)是如何了解数据在节点间的分配变化的?这就需要一个独立的协调服务,比如使用 zookeeper 来跟踪元数据,如下图所示

用“分区”来面对超大数据集和超大吞吐量

每个节点都会在 zookeeper 中进行注册,zookeeper 中维护有节点到各个分区的可靠映射,负责决策的组件在 zookeeper 中订阅这个消息。当分区分配发生改变时,zookeeper 就会通知负责决策的组件更新路由信息,使其保持在最新的状态。

除此之外也可以在各个节点间采用 流言协议 来传播集群状态的变化,这样每个节点都维护有最新的数据路由方案,当其中一个节点收到请求时,会将其转发到合适的分区节点上(对应服务发现的方案一)。

点赞
收藏
评论区
推荐文章
Stella981 Stella981
4年前
Kafka与传统消息队列的区别?
 1.首先kafka会将接收到的消息分区(partition),每个主题(topic)的消息有不同的分区,这样一方面消息的存储就不会受到单一服务器存储空间大小的限制,另一方面消息的处理也可以在多个服务器上并行。 2.其次为了保证高可用,每个分区都会有一定数量的副本(replica)。这样如果有部分服务器不可用,副本所在的服务器就会接替上来,保证应用的
Stella981 Stella981
4年前
MongoDB分片(Sharding)技术
分片(sharding)是MongoDB用来将大型集合分割到不同服务器(或者说一个集群)上所采用的方法。尽管分片起源于关系型数据库分区,但MongoDB分片完全又是另一回事。和MySQL分区方案相比,MongoDB的最大区别在于它几乎能自动完成所有事情,只要告诉MongoDB要分配数据,它就能自动维护数据在不同服务器之间的均衡。2.1MongoDB
Wesley13 Wesley13
4年前
mysql之数据分区
一:概述 通过把表分成多几区间,每个区间存储符合特定表达式的数据(即在我们创建分区表时指定每个分区存储的条件例如:PARTITIONp0VALUESLESSTHAN(100)即p0区间存储小于100的数据)。二:分区类型   即根据每个区间存储值的表达式不同,可分为如下几个类型,一般都是对数字类型或时间类型的数据进行分区。2.1 R
Stella981 Stella981
4年前
Apache Hudi重磅RFC解读之记录级别全局索引
1\.摘要Hudi表允许多种类型操作,包括非常常用的upsert,当然为支持upsert,Hudi依赖索引机制来定位记录在哪些文件中。当前Hudi支持分区和非分区的数据集。分区数据集是将一组文件(数据)放在称为分区的桶中的数据集。一个Hudi数据集可能由N个分区和M个文件组成,这种组织结构也非常方便hive/presto/sp
Stella981 Stella981
4年前
Consistent hashing一致性算法原理
最近在整理redis分布式集群,首先就整理一下分布式算法原理。常见的分区规则有哈希分区和顺序分区两种,Redis采用的是哈希分区规则。节点取余分区使用特定的数据,如Redis的键或用户ID为key,节点数量为N,则:hash(key)%N,计算出哈希值,然后决定映射到哪个节点上,如节点数为4时,哈希值的结果可能为0、1、2,3.现假
Wesley13 Wesley13
4年前
Mysql 表分区分类
针对Mysql数据库,表分区类型简析。【1】表分区类型(1)Range分区:按范围分区。按列值的范围区间进行分区存储;比如:id小于10存储在一个分区;id大于10小于20存储在另外一个分区;(2)List分区:按离散值集合分区。与range分区类似,不过它是按离散值进行分区。(3)Hash分区:按hash算法结果分区。对用户定义的表达式所返
Stella981 Stella981
4年前
Spark学习之路 (十七)Spark分区
一、分区的概念  分区是RDD内部并行计算的一个计算单元,RDD的数据集在逻辑上被划分为多个分片,每一个分片称为分区,分区的格式决定了并行计算的粒度,而每个分区的数值计算都是在一个任务中进行的,因此任务的个数,也是由RDD(准确来说是作业最后一个RDD)的分区数决定。二、为什么要进行分区  数据分区,在分布式
Stella981 Stella981
4年前
Linux系统分区方式
硬盘在使用之前,要进行分区、格式化一个硬盘可以分主分区、扩展分区、逻辑分区    主分区扩展分区<4,可以全部设置成主分区,也可以主分区扩展分区进行设置,扩展分区不能直接使用,需要在扩展分区上建立逻辑分区,逻辑分区可以有多个  主分区扩展分区编号14  逻辑分区编号只能从5开始
Stella981 Stella981
4年前
Kafka 中的消息存储在磁盘上的目录布局是怎样的?
Kafka中的消息是以主题为基本单位进行归类的,各个主题在逻辑上相互独立。每个主题又可以分为一个或多个分区,分区的数量可以在主题创建的时候指定,也可以在之后修改。每条消息在发送的时候会根据分区规则被追加到指定的分区中,分区中的每条消息都会被分配一个唯一的序列号,也就是通常所说的偏移量(offset),具有4个分区的主题的逻辑结构见下图。!(http
3A网络 3A网络
3年前
数据库系统设计:分区
数据库系统设计:分区术语澄清分区(partition),对应MongoDB、ES中的shard,HBase的Region,Bigtable的tablet,Cassandra的vnode,Couchbase的vBucket。但分区(partitioning)是最普遍的。定义每条数据(或每条记录,每行或每个文档)属于且仅属于某特定