文章目录
- [6.1 介绍](#6.1 介绍)
- [6.2 如何实现分区?](#6.2 如何实现分区?)
-
- [6.2.1 键值数据分区](#6.2.1 键值数据分区)
- [6.2.2 分区和次级索引](#6.2.2 分区和次级索引)
- [6.2.3 分区再平衡问题 && 解决方案](#6.2.3 分区再平衡问题 && 解决方案)
-
- 问题介绍
- [策略一:hash && Mod N(不推荐)](#策略一:hash && Mod N(不推荐))
- 策略二:固定数量分区
- 策略三:动态分区
- 策略四:按照节点比例分区
6.1 介绍
- 什么是分区?
分区是通过特定列的值将数据划分为逻辑独立的部分,每个分区是一个数据子集。
常见的可以用于分区的维度:时间、地理位置、类别等 - 分区的好处?
- 提高查询性能:只扫描某个表而不是整张表
- 提高管理和维护数据的能力:数据通过某个维度进行组织。
- 为什么有分区技术?
分区技术的初衷:针对海量数据场景,提高获取/更新数据的性能
分区技术和可伸缩性契合。
6.2 如何实现分区?
6.2.1 键值数据分区
目标
将数据和查询负载均匀分布到各个节点中。
方案一:随机分配
随机分配可以保证负载均衡,但是当读取一个特定值时,无法知道该值在那个分区,只能遍历全表。
方案二:根据键的范围分区
定义:每个分区定义一个最小值和最大值。
优点:
- 查询时可以找到迅速找到分区
缺点: - 数据分布无法保证均匀,可能会导致某个(些)分区成为"热点"
方案三:散列(hash)分区--一致性哈希算法
优点:
- 可以公平的分配键,负载比较均衡
缺点: - 范围查询性能没有提升
6.2.2 分区和次级索引
次级索引的分区问题
当前数据库,例如 mysql、oracle 中,分区键中必须是主键的一部分,因此主键是可以快速定位到分区的。
但是次级索引列和分区键可能是两个不同的列,通过次级索引列的每次操作,就需要对所有数据进行操作。
方案一:基于文档的分区-本地索引
这种索引优点:
- 每个分区完全独立,只需要处理当前分区中的信息
缺点
- 不会将某种特定的 key 放在一起(color 所有数据),导致搜索时必须全表扫描
应用的数据库如 MongoDB、Elasticsearch 等。
方案二:基于关键词的分区-全局索引
构建一个覆盖所有分区数据的全局索引。全局索引也不可以放在一个节点上,需要进行分区。
优点:
- 读取效率更高
缺点:
- 写入速度慢 && 复杂
- 需要跨分区的事务
6.2.3 分区再平衡问题 && 解决方案
问题介绍
随时间推移,数据库以下情况都需要数据 && 请求从一个节点转移到另一个节点种,将负载从一个节点转移到另一个节点的过程称为再平衡。
- 查询吞吐量增加
- 数据集大小增加
- 机器故障
再平衡目标:
- 负载应该公平
- 再平衡进行中,服务可用
- 节点间移动的数据应该尽量少
策略一:hash && Mod N(不推荐)
策略执行:先对 key 进行 hash,对结果通过 mod n 分区。
节点数量 n 增加时,大量原有数据必须迁移,成本过大。
策略二:固定数量分区
分区数量 > 节点数量,每个节点分配多个分区。
优点:
- 分区在节点种移动
- 分区总数不变
缺点: - 无法很好的评估分区数量
策略三:动态分区
采用关键字区间分区的数据库,如果边界设置有问题,可能导致数据倾斜到一个分区中。
- 按键的范围进行分区的数据库(如HBase和RethinkDB)会动态创建分区。
- 当分区增长到超过配置的大小时(在HBase上,默认值是10GB),会被分成两个分区,每个分区约占一半的数据。
- 与之相反,如果大量数据被删除并且分区缩小到某个阈值以下,则可以将其与相邻分区合并。此过程与B树顶层发生的过程类似。
优点: - 分区数量适应总数据量
缺点: - 空数据库从 1 个分区开始,导致所有写入必须单个节点处理,其他节点空闲。
策略四:按照节点比例分区
动态分区和固定数量的分区,分区数量都与节点数量无关。
Cassandra和Ketama使用的第三种方法是使分区数与节点数成正比:每个节点有固定数量的分区。
- 当节点数不变,分区大小与数据集大小成比例增长;
- 当节点数改变,分区大小将变小。
操作方式:
- 当一个新节点加入集群时,它随机选择固定数量的现有分区进行拆分,然后占有这些拆分分区中每个分区的一半,同时将每个分区的另一半留在原地。
- 随机化可能会产生不公平的分割,但是平均在更大数量的分区上时,新节点最终从现有节点获得公平的负载份额。
- 随机选择分区边界要求使用基于散列的分区(可以从散列函数产生的数字范围中挑选边界)。实际上,这种方法最符合一致性哈希的原始定义。