你真的理解分布式数据的分区吗?

news2024/11/24 11:57:43

分布式数据存储是指将数据分散存储在多个节点或服务器上的技术。而分区是将数据划分为逻辑上的片段或部分,每个分区可以在分布式系统中的不同节点上存储。分区主要是为了可扩展性。不同的分区可以放在不共享集群中的不同节点上,可以帮助实现负载均衡、高可用性、并行处理、数据本地性优化以及系统的扩展性和灵活性。通过合理的分区策略,可以充分发挥分布式存储系统的优势,提供高效、可靠的数据存储和处理能力。

  1. 数据划分与负载均衡:通过将数据划分为多个分区,可以将数据在分布式系统中均匀地分散存储在不同的节点上。这样可以实现负载均衡,避免某个节点负载过重,提高系统的性能和可扩展性。
  2. 高可用性和容错性:将数据划分为多个分区后,每个分区可以在不同的节点上复制多个副本,以实现数据的冗余和容错性。如果某个节点发生故障或网络中断,其他节点上的副本仍然可用,确保数据的高可用性和可靠性。
  3. 并行处理和查询优化:分区可以使分布式系统能够同时处理多个分区上的数据,实现并行计算和处理。这对于大规模数据处理和复杂查询非常重要,可以提高处理速度和性能。
  4. 数据本地性和局部性优化:通过将数据划分为分区,并将每个分区存储在靠近数据的节点上,可以实现数据本地性和局部性优化。这意味着在执行查询或操作时,系统可以更快地访问和处理本地节点上的数据,减少网络延迟,提高数据访问效率。
  5. 扩展性和灵活性:分区可以使系统具备良好的扩展性和灵活性。当需要增加存储容量或处理能力时,可以通过增加节点和调整分区策略来实现系统的扩展,而不需要对整个系统进行大规模的改变或迁移。

分区通常与复制结合使用,使得每个分区的副本存储在多个节点上。 这意味着,即使每条记录属于一个分区,它仍然可以存储在多个不同的节点上以获得容错能力。一个节点可能存储多个分区。每个分区领导者(主)被分配给一个节点,追随者(从)被分配给其他节点。 每个节点可能是某些分区的领导者,同时是其他分区的追随者。
在这里插入图片描述
那么既然要对数据进行划分,放在不同的分区上,首先我们需要解决的一个重要问题就是如何划分数据?

为什么说这个问题很重要呢?

如果分区是不公平的,一些分区比其他分区有更多的数据或查询,我们称之为数据偏斜。数据偏斜的存在使分区效率下降很多。加入有10个分区,在极端的情况下,所有的负载可能压在一个分区上,其余9个节点空闲的,瓶颈落在这一个繁忙的节点上。不均衡导致的高负载的分区 被称为热点。

避免热点最简单的方法是将记录随机分配给节点。但进而导致的一个很大的问题就是无法知道我们想要查询的值实际上是落在那个节点上,需要扫描全部分区才能获取结果,这种方式带来的性能损耗是不能接受的。

所以接下来介绍一下我们常见的集中数据分配策略:

分片策略

范围分区

每个分区指定一块连续的键范围(从最小值到最大值)。一个简单的比喻就是图书馆中某类书根据字母顺序有序排列
在这里插入图片描述
这种分区的好处是进行范围扫描非常简单,但可能会导致热点,比如字母A的书籍特别受欢迎,80%的用户访问都会集中在A类书籍,就会导致对应的机器负载变得很大。

为了解决热点的问题,我们可以在分片键增加干扰项:书籍+作者,但这样也会增加查询复杂度

散列分区

首先,对要存储的数据进行散列计算。通常使用散列函数(如MD5、SHA-1、SHA-256等)将数据转换为固定长度的散列值。散列函数具有将任意大小的输入转换为固定长度输出的特点,且输出值具有高度随机性。散列计算后,根据散列值的范围将数据映射到相应的分区。分区的数量通常是固定的,每个分区可以在分布式系统中的不同节点上存储。映射过程可以使用模运算或范围映射等算法,将散列值映射到特定的分区。将散列后的数据存储到对应的分区中。当需要访问特定数据时,再次对数据进行散列计算得到散列值,并通过映射算法确定存储该数据的分区。然后,通过访问对应的分区,从相应的节点上获取数据。

好的散列函数可以将将偏斜的数据均匀分布,当然代价就是失去高效的范围查询能力:使用了基于散列的分区模式,则任何范围查询都必须发送到所有分区
在这里插入图片描述
进而我们也可以想到,为了减少分区节点的增减对与映射的影响,可以采用一致性hash优化

我们可以思考一下如何负载倾斜与消除热点?

哈希分区可以帮助减少热点。但是,它不能完全避免:在极端情况下,所有的读写操作都是针对同一个键的,所有的请求都会被路由到同一个分区。对于高热点数据,我们可以在主键的开始或结尾添加一个随机数(比如0-100),但查询时必须从100个分布中读取数据并合并,同时还要记录哪些数据是属于热点数据,普通数据就没必要这么操作了,毕竟也是有一定代价的。

分片与次级索引

接下来我们应该考虑另外一个问题了,为了提高查询效率,很多数据库都会支持刺激索引来满足不同场景下的不同查询条件,分片时我们应该如何处理次级索引的更新问题呢?

有两种用二级索引对数据库进行分区的方法:基于文档的分区(document-based)和基于关键词(term-based)的分区。

按文档的二级索引

举一个列子,假设有一个存储汽车信息的数据表,每个列表都有一个唯一的ID——称之为文档ID——并且用文档ID对数据库进行分区(例如,分区0中的ID 0到499,分区1中的 ID 500到999等)。如果用户想按照颜色进行搜索,那么按文档的二级索引表现形式如下:
在这里插入图片描述
在这种索引方法中,每个分区是完全独立的:每个分区维护自己的二级索引,仅覆盖该分区中的文档。它不关心存储在其他分区的数据。文档分区索引也被称为本地索引。如果要按照颜色进行查询,则需要将查询发送到所有分区,并合并所有返回的结果。这种查询分区数据库的方法有时被称为分散/聚集,并且可能会使二级索引上的读取查询相当昂贵。即使并行查询分区,分散/聚集也容易导致尾部延迟放大。

根据关键词(Term)的二级索引

它与本地索引的区别如下:
在这里插入图片描述
它构建一个覆盖所有分区数据的全局索引,而不是给每个分区创建自己的次级索引。全局索引也必须进行分区,但可以采用与主键不同的分区方式。

关键词分区的全局索引优于文档分区索引的地方点是它可以使读取更有效率:不需要分散/收集所有分区,客户端只需要向包含关键词的分区发出请求。全局索引的缺点在于写入速度较慢且较为复杂,因为写入单个文档现在可能会影响索引的多个分区(文档中的每个关键词可能位于不同的分区或者不同的节点上) 。

理想情况下,索引总是最新的,写入数据库的每个文档都会立即反映在索引中。但是,在关键词分区索引中,这需要跨分区的分布式事务,并不是所有数据库都支持。在实践中,对全局二级索引的更新通常是异步的(也就是说,如果在写入之后不久读取索引,刚才所做的更改可能尚未反映在索引中)。

分区再平衡

我们的数据库可能会出现各种情况,比如机器的CPU、磁盘达到限制了,不得不需要扩展更多的磁盘CPU,机器出现故障需要替换等等,所有这些更改都需要数据和请求从一个节点移动到另一个节点。 将负载从集群中的一个节点向另一个节点移动的过程称为再平衡。

再平衡通常都要满足一些最低要求:

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

平衡策略

我们首先需要知道一点,hash mod N,这种策略是绝对不行的,因为扩缩容会导致N数据的变化,N的变化会导致数据路由出错

那么我们就可以想到,是否可以创建固定数量的分区?当然可以,像redis就是这么干的,创建比节点更多的分区,只有分区在节点之间的移动。分区的数量不会改变,键所指定的分区也不会改变。唯一改变的是分区所在的节点。这种变更并不是即时的 — 在网络上传输大量的数据需要一些时间 —所以在传输过程中,原有分区仍然会接受读写操作。
在这里插入图片描述
但需要注意的是,要选择一个合适大小的分区数量,如果分区非常大,再平衡和从节点故障恢复变得昂贵。但是,如果分区太小,则会产生太多的开销。

并且这种对与hash分片的数据是比较合适的,对于使用键范围分区的数据库,具有固定边界的固定数量的分区将非常不便:如果出现边界错误,则可能会导致一个分区中的所有数据或者其他分区中的所有数据为空。手动重新配置分区边界将非常繁琐。

对了解决范围分区数据库的问题,我们想到是否可以支持动态分片呢?

当然可以,如HBase,MongoDB,按键的范围进行分区的数据库会动态创建分区。当分区增长到超过配置的大小时(在HBase上,默认值是10GB),会被分成两个分区,每个分区约占一半的数据。与之相反,如果大量数据被删除并且分区缩小到某个阈值以下,则可以将其与相邻分区合并。此过程与B树顶层发生的过程类似。每个分区分配给一个节点,每个节点可以处理多个分区,就像固定数量的分区一样。大型分区拆分后,可以将其中的一半转移到另一个节点,以平衡负载。在HBase中,分区文件的传输通过HDFS(底层分布式文件系统)来实现

动态分区的一个优点是分区数量适应总数据量。如果只有少量的数据,少量的分区就足够了,所以开销很小;如果有大量的数据,每个分区的大小被限制在一个可配置的最大值

需要注意的是,一个空的数据库从一个分区开始,因为没有关于在哪里绘制分区边界的先验信息。数据集开始时很小,直到达到第一个分区的分割点,所有写入操作都必须由单个节点处理,而其他节点则处于空闲状态。为了解决这个问题,HBase和MongoDB允许在一个空的数据库上配置一组初始分区(这被称为预分割(pre-splitting))

动态分区不仅适用于数据的范围分区,而且也适用于散列分区。从版本2.4开始,MongoDB同时支持范围和哈希分区,并且都是进行动态分割分区。

上面无论是固定数量分片还是动态分片,都与节点数量无关(动态分片是与分区数据量有关,单个分片数据量增长到一定程度,会分裂),那么我们可不可以支持分区数量随节点数量变动呢?

也可以,这种就是按照节点比例进行分区。每个节点具有固定数量的分区。这种情况下,每个分区的大小与数据集大小成比例地增长,而节点数量保持不变,但是当增加节点数时,分区将再次变小。由于较大的数据量通常需要较大数量的节点进行存储,因此这种方法也使每个分区的大小较为稳定。

当一个新节点加入集群时,它随机选择固定数量的现有分区进行拆分,然后占有这些拆分分区中每个分区的一半,同时将每个分区的另一半留在原地。随机化可能会产生不公平的分割,但是平均在更大数量的分区上时,新节点最终从现有节点获得公平的负载份额。

随机选择分区边界要求使用基于散列的分区(可以从散列函数产生的数字范围中挑选边界)。实际上,这种方法最符合一致性哈希的原始定义

然后我们就需要考虑是手动还是自动平衡

全自动重新平衡更方便

手动平衡更安全。再平衡是一个昂贵的操作,因为它需要重新路由请求并将大量数据从一个节点移动到另一个节点。如果没有做好,这个过程可能会使网络或节点负载过重,降低其他请求的性能。特别是自动化与自动故障检测相结合可能十分危险,可能存在误判

请求路由

随着分区重新平衡,分区对节点的分配也发生变化,客户端请求时,怎么知道应该去访问哪个节点的数据?

一般来说,有以下三种形式:

  1. 允许客户联系任何节点(例如,通过循环策略的负载均衡(Round-Robin LoadBalancer))。如果该节点恰巧拥有请求的分区,则它可以直接处理该请求;否则,它将请求转发到适当的节点,接收回复并传递给客户端。(redis)
  2. 首先将所有来自客户端的请求发送到路由层,它决定了应该处理请求的节点,并相应地转发。此路由层本身不处理任何请求;它仅负责分区的负载均衡。(mongos)
  3. 要求客户端知道分区和节点的分配。在这种情况下,客户端可以直接连接到适当的节点,而不需要任何中介。
    在这里插入图片描述
    许多分布式数据系统都依赖于一个独立的协调服务,比如ZooKeeper来跟踪集群元数据。HBase和Kafka也使用ZooKeeper来跟踪分区分配。MongoDB具有类似的体系结构,但它依赖于自己的配置服务器(config server) 实现和mongos守护进程作为路由层。

Cassandra和Riak采取不同的方法:他们在节点之间使用流言协议(gossip protocol) 来传播群集状态的变化。请求可以发送到任意节点,该节点会转发到包含所请求的分区的适当节点。这个模型在数据库节点中增加了更多的复杂性,但是避免了对像ZooKeeper这样的外部协调服务的依赖。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/530418.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

玩转Google开源C++单元测试框架Google Test系列(gtest)之四 - 参数化

一、前言 在设计测试案例时,经常需要考虑给被测函数传入不同的值的情况。我们之前的做法通常是写一个通用方法,然后编写在测试案例调用它。即使使用了通用方法,这样的工作也是有很多重复性的,程序员都懒,都希望能够少…

Liunx基础命令 - cd命令

cd命令 – 切换目录 cd命令来自英文词组“change directory”的缩写,其功能是用于更改当前所处的工作目录,路径可以是绝对路径,也可以是相对路径,若省略不写则会跳转至当前使用者的家目录。 **语法格式:**cd [参数] …

VMware Workstation 17 Pro安装配置CentOS 7与ssh工具链接配置

VMware Workstation 17 Pro安装配置CentOS 7与ssh工具链接配置 下载安装虚拟机VMware Workstation 17 Pro 虚拟机官网:点击直达 下载Cent os 7 镜像文件 123网盘地址:点击直达 提取码1213 在虚拟机中安装Cent os 7 第一步 点击 创建新的虚拟机 第二步 默…

解释什么是蓝绿发布?

蓝绿发布(Blue-green release)是一种软件部署策略,主要用于应对新版本软件在生产环境中的测试和部署。这种策略将新版本软件分为两个阶段:蓝色阶段和绿色阶段。蓝色阶段通常在开发和测试环境中进行,而绿色阶段则在生产环境中进行。 蓝色阶段…

C语言运算符:赋值与计算

目录 赋值运算符 算术运算符 赋值运算符 下表列出了 C 语言支持的赋值运算符: 运算符描述实例简单的赋值运算符,把右边操作数的值赋给左边操作数C A B 将把 A B 的值赋给 C加且赋值运算符,把右边操作数加上左边操作数的结果赋值给左边操…

C语言基础知识:关系运算符与逻辑运算符

目录 1、关系运算符介绍 2、应用示例 3、逻辑运算符介绍 4、逻辑表达式的书写 5、不得不说的逻辑非 1、关系运算符介绍 关系运算(Relational Operators),用于判断条件,决定程序的流程。 关系数学中的表示C语言的表示小于&l…

GPT神奇应用:生成菜谱

正文共 662 字,阅读大约需要 2 分钟 料理新手/爱好者必备技巧,您将在2分钟后获得以下超能力: 快速生成菜谱 Beezy评级 :B级 *经过简单的寻找, 大部分人能立刻掌握。主要节省时间。 推荐人 | Kim 编辑者 | Linda ●图…

VMWare 虚拟机创建 + 初始化

目录 概述 1. VMware创建虚拟机 2. IP 配置 nmtui nmcli 3. Yum 源配置 光盘的Packages作为Yum源 配置开机自动挂载(光盘) 配置私有Yum仓库 跟新私有yum仓库 报错和修复 4. 文件共享系统配置 跟新配置文件/etc/hosts /etc/yum.repo.d/ftp.repo 同步配置文件 测试…

HLS入门实现一个led灯的闪烁

文章目录 前言一、HLS是什么?与VHDL/Verilog编程技术有什么关系?1、HLS简介2、开发流程3、HLS与VHDL/Verilog编程技术有什么关系? 二、2. HLS有哪些关键技术问题?目前存在什么技术局限性?1.关键技术问题2、技术局限性 三、使用 HLS 完成 le…

第十二章创建模式—享元模式

文章目录 享元模式概述结构 实例优缺点和使用场景使用场景JDK源码解析 结构型模式描述如何将类或对象按某种布局组成更大的结构,有以下两种: 类结构型模式:采用继承机制来组织接口和类。 对象结构型模式:釆用组合或聚合来组合对象…

渗透测试--2.漏洞探测和利用

目录 一.漏洞分类 二.漏洞探测 三.漏洞利用 四.漏洞扫描 1.Nessus 2.Web应用漏洞扫描器——DVWA 五.Metasploit漏洞利用 一.漏洞分类 网络漏洞 系统漏洞 应用漏洞 人为不当配置 二.漏洞探测 渗透测试是一种测试网络、应用程序和系统安全性的方法,旨在发现…

Xilinx FPGA DDR3设计(三)DDR3 IP核详解及读写测试

引言:本文我们介绍下Xilinx DDR3 IP核的重要架构、IP核信号管脚定义、读写操作时序、IP核详细配置以及简单的读写测试。 01.DDR3 IP核概述 7系列FPGA DDR接口解决方案如图1所示。 图1、7系列FPGA DDR3解决方案 1.1 用户FPGA逻辑(User FPGA Logic&#…

玩转Google开源C++单元测试框架Google Test系列(gtest)之七 - 深入解析gtest

一、前言 “深入解析”对我来说的确有些难度,所以我尽量将我学习到和观察到的gtest内部实现介绍给大家。本文算是抛砖引玉吧,只能是对gtest的整体结构的一些介绍,想要了解更多细节最好的办法还是看gtest源码,如果你看过gtest源码…

麒麟操作系统软件更新灾难连篇之一:中文输入法消失

今天在麒麟操作系统开QQ总是过一会儿就闪退,于是进软件商店看看是否有更新。 真是不看不知道,一看吓一跳,居然有几十个软件更新,照常理,软件升级后应该是更加好用,于是先把QQ、五笔字型、搜狗输入法等几个常…

centos7.9搭建redis6.0.6哨兵模式

redis6.0.6哨兵模式搭建文档 1.准备工作1.1 ip规划安装依赖(三台机器都操作)1.3 gcc升级(三台机器都操作) 2.安装redis(三台机器都操作)2.1 获取安装包2.2 解压2.3 编译2.4 验证上一步是否正确2.5 安装2.6…

Windows10安装二进制Mysql-5.7.41和汉化

1.创建my.ini [mysqld] ##skip-grant-tables1 port 3306 basedirD:/webStudy/mysql-5.7.41 datadirE:/adata/mysqlData max_connections200 character-set-serverutf8 default-storage-engineINNODB sql_modeNO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES [mysql] default-char…

Liunx基础命令 - which命令

which命令 – 查找命令文件 ​ which命令的功能是用于查找命令文件,能够快速搜索二进制程序所对应的位置。如果我们既不关心同名文件(find与locate),也不关心命令所对应的源代码和帮助文件(whereis)&#…

C++中类的静态成员变量与静态成员函数

static声明为静态的,称为静态成员。 不管这个类创建了多少个对象,静态成员只有一个拷贝,这个拷贝被所有属于这个类的对象共享。 静态成员 属于类 而不是对象。 静态变量,是在编译阶段就分配空间,对象还没有创建时&…

ARM-栈帧(一)

ARM 栈帧 本系列均以 corter-A7(armv7-a) 为例 在 ARM 中,通常为满减栈(Full Descending FD), 也就是说,堆栈指针指向堆栈内存中最后一个填充的位置,并且随着每个新数据项被压入堆栈而递减。 栈的本质 要理解栈的本…

二叉搜索树、AVL树、红黑树底层源码以及迭代器模拟实现,map/set的封装

这次给大家分享的还是关于二叉树部分的内容,之前的文章已经分享过一些二叉树的基础知识,如果不了解的朋友可以看看:二叉树以及堆和堆排序。普通的二叉树其实是没有什么实际的应用价值的,而map和set大家用过或者听过吗?…