DDIA-数据分区

Posted by keys961 on March 3, 2019

1. 键值数据的分区

1.1. 基于关键字区间分区

即以一段连续的关键字或关键字区间分区。

优点:区间上的分区也利于排序和范围查询。

缺点:容易在热点下的负载不均衡。(需要通过额外信息作为分区的依据,解决这种问题)

1.2. 基于关键字散列分区

根据关键字的散列值进行分区(为每个分区划分散列值范围)。分区边界可为均匀间隔(固定分配),也可为伪随机选择(一致性散列)

一致性散列:详细说明在,很容易理解。在散列空间(可以用散列环看),用(节点自身的)散列值确定分区边界(即一段弧)。

优点:缓解某些热点问题

缺点:区间查询需要将请求发送给所有节点

1.3. 负载倾斜与热点

对于某个关键字的热点,大多数系统无法自动消除这种高度倾斜的负载,需要应用层控制。

一种简单的方法:对热点关键字附带一个随机数,从而将其分配到不同分区,但是读操作时需要额外将所有不同分区的相关数据合并,带来不必要的开销

2. 分区与二级索引

二级索引的索引值不能唯一标识一条记录,因此主要的挑战是:不能规整地映射到分区。

一般有两种方法:基于文档的分区,基于词条的分区

2.1. 基于文档分区的二级索引

每个分区独立,各自维护自己的二级索引,只负责自己分区内的文档(行或者条目)。即每次写时,只需处理包含目标ID的分区的二级索引,因此叫做本地索引(不是全局索引)。

缺点:查询时,必须查询所有分区,然后合并,带来巨大延迟(读跨分区

2.2. 基于词条的二级索引

构建的是全局索引,但是索引也会根据对应策略分区

如对CarColor建立二级索引,前0~499在分区1,后500~999在分区2。Color:red索引可以在分区1上,Color:black可在分区2上,但是它们是全局的,记录了2个分区的索引项(如Color:red = [191, 688]

优点:查询更加高效,不需并行查询然后再合并

缺点:写入慢(写跨分区),因为二级索引可能较多且复杂,且二级索引所在的分区可能和条目本身所在分区一样(可用异步更新减少性能影响)

3. 分区再平衡

分区再配合(动态平衡):即数据和请求从一个节点转移到另一个节点的负载迁移

目标:负载分布更均匀,平衡过程中可用,避免不必要的迁移

3.1. 动态再平衡策略

3.1.1. 为何不取模(对节点个数)

采用$hash(key) \% N$($N$为节点个数)时,当节点个数变化时,会导致很多关键字需要迁移。

3.1.2. 固定数量分区

首先创建远超实际节点数的分区数,分区数始终不变,然后为每个节点分配多个分区。

当节点加入或离开时,只需均匀拿走或添加几个分区,直到再次平衡为止。再次期间,旧分区依旧可用。

分区数量不应太大或太小,分区数应和数据总量成正比

3.1.3. 动态分区

当一个分区数据量过大时,自动拆分为多个分区;若一个分区数据量过小,自动和邻近分区合并

优点:分区数量可根据数据量自动配置,且不仅适用于关键字区间分区,也适用于基于散列的分区

3.1.4. 按节点比例分区

即分区数和节点数成正比,每个节点拥有固定的分区数。这种方法可维持分区大小的稳定。

节点加入时,根据算法/随机,从集群中选择固定数量的分区,取走它们一部分的数据量,另一部分保留在原节点。

前提:要求使用基于散列的分区

3.2. 自动与手动再平衡操作

自动:方便,操作少,但可能存在风险,并影响性能和可用性

手动:平衡响应慢,但风险少

4. 请求路由

一类典型的服务发现的问题。

一般有三种方式:

  • 客户端可请求任意节点,节点可返回结果或转发到合适的节点(每个节点都要分区与节点的关系)

  • 客户端请求到路由层,路由层转发请求到合适节点(路由层需要知道分区与节点的关系)

  • 客户端感知分区与节点的关系,直接请求对应的节点

    可由外部独立的协调服务实现,如利用ZooKeeper。节点向ZooKeeper集群注册自己(插入树形节点),路由层/感知客户端订阅ZooKeeper/从ZooKeeper获取节点信息获取最新状态。

    一个小demo在这里,利用ZooKeeper简单实现了软负载平衡。

4.1. 并行查询执行

对于大规模并行处理(MPP),主要用于数据分析的关系数据库,查询很复杂。

MPP查询优化器将复杂的查询分解成许多执行阶段和分区,以便于在集群不同节点上执行,尤其是全表扫描的查询。