每个分区都是自己的小型数据库,尽管数据库可能支持同时进行多个分区的操作。分区主要是为了可扩展性。不同的分区可以放在不共享集群中的不同节点上。因此,大数据集可以分布在多个磁盘上,并且查询负载可以分布在多个处理器上。
分区目标是将数据和查询负载均匀分布在各个节点上。如果分区是不公平的,一些分区比其他分区有更多的数据或查询,称之为偏斜。在极端的情况下,所有的负载可能压在一个分区上,其余9个节点空闲的,瓶颈落在这一个繁忙的节点上。不均衡导致的高负载的分区被称为热点hot spot。
一种分区的方法是为每个分区指定一块连续的键范围(从最小值到最大值),如纸百科全书的卷。缺点是某些特定的访问模式会导致热点。
由于偏斜和热点的风险,许多分布式数据存储使用散列函数来确定给定键的分区。不幸的是,通过使用Key散列进行分区,我们失去了键范围分区的一个很好的属性:高效执行范围查询的能力。
在这种索引方法中,每个分区是完全独立的:每个分区维护自己的二级索引,仅覆盖该分区中的文档。它不关心存储在其他分区的数据。如果要搜索时,则需要将查询发送到所有分区,并合并所有返回的结果。被称为分散/聚集。
我们可以构建一个覆盖所有分区数据的全局索引,而不是给每个分区创建自己的次级索引(本地索引)。但是,我们不能只把这个索引存储在一个节点上,因为它可能会成为瓶颈,违背了分区的目的。全局索引也必须进行分区,但可以采用与主键不同的分区方式。
我们可以通过关键词本身或者它的散列进行索引分区。根据它本身分区对于范围扫描非常有用(例如对于数字,像汽车的报价),而对关键词的哈希分区提供了负载均衡的能力。
全局索引的缺点在于写入速度较慢且较为复杂,因为写入单个文档现在可能会影响索引的多个分区。
创建比节点更多的分区,并为每个节点分配多个分区。例如,运行在10个节点的集群上的数据库可能会从一开始就被拆分为1,000个分区,因此大约有100个分区被分配给每个节点。
如果一个节点被添加到集群中,新节点可以从当前每个节点中窃取一些分区,直到分区再次公平分配。
只有分区在节点之间的移动。分区的数量不会改变,键所指定的分区也不会改变。唯一改变的是分区所在的节点。这种变更并不是即时的,在网络上传输大量的数据需要一些时间,所以在传输过程中,原有分区仍然会接受读写操作。
一开始配置的分区数就是您可以拥有的最大节点数量,所以需要选择足够多的分区以适应未来的增长。
按键的范围进行分区的数据库(如HBase和RethinkDB)会动态创建分区。当分区增长到超过配置的大小时(在HBase上,默认值是10GB),会被分成两个分区,每个分区约占一半的数据。与之相反,如果大量数据被删除并且分区缩小到某个阈值以下,则可以将其与相邻分区合并。此过程与B树顶层发生的过程类似。
每个分区分配给一个节点,每个节点可以处理多个分区,就像固定数量的分区一样。大型分区拆分后,可以将其中的一半转移到另一个节点,以平衡负载。在HBase中,分区文件的传输通过HDFS(底层分布式文件系统)来实现。
通过动态分区,分区的数量与数据集的大小成正比,因为拆分和合并过程将每个分区的大小保持在固定的最小值和最大值之间。另一方面,对于固定数量的分区,每个分区的大小与数据集的大小成正比。在这两种情况下,分区的数量都与节点的数量无关。
第三种方法是使分区数与节点数成正比——换句话说,每个节点具有固定数量的分区。每个分区的大小与数据集大小成比例地增长,而节点数量保持不变,但是当增加节点数时,分区将再次变小。当一个新节点加入集群时,它随机选择固定数量的现有分区进行拆分,然后占有这些拆分分区中每个分区的一半,同时将每个分区的另一半留在原地。
允许客户联系任何节点(例如,通过循环策略的负载均衡)。如果该节点恰巧拥有请求的分区,则它可以直接处理该请求;否则,它将请求转发到适当的节点,接收回复并传递给客户端。
要求客户端知道分区和节点的分配。在这种情况下,客户端可以直接连接到适当的节点,而不需要任何中介。
许多分布式数据系统都依赖于一个独立的协调服务,比如ZooKeeper来跟踪集群元数据。 每个节点在ZooKeeper中注册自己,ZooKeeper维护分区到节点的可靠映射。 其他参与者(如路由层或分区感知客户端)可以在ZooKeeper中订阅此信息。 只要分区分配发生的改变,或者集群中添加或删除了一个节点,ZooKeeper就会通知路由层使路由信息保持最新状态。
原文地址:https://www.cnblogs.com/Ryan16231112/p/12315100.html