在分布式存储里面,比较常见的有kafka,Hbase,HDFS,fastDFS等,这里面涉及到文件的分布式存储以及数据的分布式存储。分布式存储的背景:就是将数据文件分散的存储到分布式集群的每一个节点,提升了存储的容量(大数据化);同时尽量凸显分布式的检索能力。分布式存储的原理:分层化的hash映射、数据组织的数据摘要以及块数据的叶子索引结构;这几种数据结构相结合的方式提供快速检索的能力和存储结构。
先说说HDFS,其实比较早的分布式存储解决方案;HDFS读写都是都是从NameNode点开始的,获取对应目录结构的region所有在的dataNode,然后从对应的dataNode读写数据。HDFS内部节点的管理是依据zookeeper. 每一个节点都会分配region(节点最多也就是1000个region),每一个节点的region信息存储到master节点,集群的NameNode节点存储每一个节点的元region、block(block默认大小是64MB;3.0版本是128MB)信息,还有目录树结构数据对应block信息,辅助master节点进行元数据的。region信息在master上生成一个hash结构,在读取数据的数据的时候可以很快定位到具体的节点和region, 网络通信是依靠NIO建立的socket通信,同时region文件读取是DMA技术(换句话说hdfs底层是依靠netty实现的通信)。
Hbase本质上在文件上存储也是基于HDFS,但是在管理region上,master节点上专门建立了一个table,来存储region对应位置region中包含block,block之间是靠着链表存储的。Hbase存储是默认将id按照顺序分割不同的region,然后region又会分为小的block。每一个block都有最大id来标记,类似于kafka patition存储一样,里面包含segment,segment信息描述文件,然后block依托着链表来存储连接。每一个block内部存储的数据也是按照id顺序存储的,然后每一个block都对应一个叶子索引就是B+树。对于某一列属性建立二级索引和列对应起来,那么就会建立另外以某列属性值为key,行的id为value建立B+树。
Hbase还有很重要的缓存机制,上面只是说了数据文件的存储机制,其实hbase的高性能很大一部分上来自于基于内存的缓存机制。在读写数据的时候,client都会请求zookeeper,获取最新的region metatable信息,也就是region信息,那么client才会知道去链接哪一个region。在写数据的时候(metatable也会记录每一个region对应的最大id),也会有对应的region节点选择和链接。
首先将数据写到write_ahead_log(简称WAL,这和mysql的binlog类似),然后write_ahead_log读到内存中,会在内存中按照对应id序列拍好序的(整个内存块mem-store),当mem-store到一定的大小就会IO写到Hfile中,不同的mem-store块对应写到不同的Hfile,Hfile达到一定的大小就会合并在一起形成新的Block。
读数据也有对应的内存块blcok-cache,每一个block都会有对应一到多个blcok-cache,每一个blcok-cache也是按照id组织好的。再次读取的时候会获取blcok-cache数据,同时也会获取mem-store数据综合覆盖(相同id数据条目,因为在内存中存储也是按照顺序的,所以在检索和获取的时候很高效),获取最新的数据。
下面说一下数据表文件存储的数据细节,首先每一个表文件都有表描述文件,里面有字段的顺序,字段的所占的字节数(字段长度,该表描述文件一般是表名.tb)。其次就是表数据文件(一般就是表名.data),每一条数据就是按照字段的顺序排列存储,每一条数据结束有结束符号。数据库(mysql存储引擎innodb/mySAM)都是按照数据页来存储数据的,也就是每1000条(默认页数据数)放在一个文件里面,这就是一页数据。页数据有对应得目录描述,就是每一页起始id信息,页信息在目录文件中按照顺序存储得,内存加载目录信息,按照每一页得描述字段长度在内存形成一个双向链表结构。(下图是内存加载目录结构文件,形成得双向链表)
所有的数据依据建立的索引的字段建立B+树结构(主键默认会创建索引),然后我们知道这个索引结构是B+树,关键这个树结构是怎么存储到存盘文件中的,以xx.idx来命名。这个索引结构存储到磁盘文件之后,我们还能很多读取这个文件在内存中很快映射解析出这个树结构。首先我们看下二叉树磁盘存储的案例:
完全二叉树从根结点到倒数第二层满足完美二叉树,最后一层可以不完全填充,其叶子结点都靠左对齐。
30
/ \
20 40
/ \ / \
15 25 35 45
/ \
5 10
换句话说,对于完全二叉树,将层次顺序遍历的序列存储到文件中。当我们从文件读取时,可以推断出第一个元素是根节点,然后接下来2个元素是级别1的二个节点,接下来读出的4个元素是级别2的节点,依此类推。因此可以非常容易地构造这棵完全二叉树。
30 20 40 15 25 35 45 5 10
但是对于给定的树,并不是完全二叉树,即中间节点可能有缺失。比如,下面的二叉树中节点40的左子节点有缺失。在这种情况下,当层次遍历并序列化至文件时,需要人为添加一个值(比如-1)来表达当前节点的缺失。前提是,我们树的所有节点的值都是正数。
30
/ \
20 40
/ \ \
15 25 45
\
10
基于上述想法,我们将-1添加到缺失的节点中,从而将一个普通的二叉树转换成完全二叉树:
30
/ \
20 40
/ \ / \
15 25 -1 45
/ \
-1 10
对应地,上面转换后的完全二叉树持久化到文件的内容如下:
30 20 40 15 25 -1 45 -1 10
那么B+树也按照层级来顺序存储到文件中,解析的时候按照层级标识符来逐层构建B+树。上述就算完全讲述完了数据库表数据文件存储的方案,以及如何快速查询的方案。但是具体到mysql上还存在一些差异,可能对于某一些数据库每一页也存储了对应的B+树索引结构。当然对于全面的B+索引结构文件需要尽可能的小,需要一次性加载到内存中,然后遍历树结构,定位到叶子链表中不同的行数据(条件区间在双向链表中是连续的一段),然后再去目录查到对应的页,把数据查询出来。
对于分布式文件存储,文件被分割成很多块,每一个块都对应一个子文件。这些子文件会被记录到块目录中,然后查询的时候会通过目录找到对应的文件信息。
我们知道内存中数据存储都是有条目数据记录数据存储的起始位置;在内存中存储也是有页(页管理)进行管理的,有页表记录页的位置和顺序。对于磁盘存储也是有最小的单元--扇区,一个扇区最小的存储大小是4KB,文件在磁盘存储的时候也是有记录的,也有所在目录映射表,创建一个目录的时候,会分配存储空间和范围,创建一个文件会记录目录信息以及存储大小(存储所涉及到扇区范围)。
ceph存储原理
Ceph是⼀种为优秀的性能、可靠性和可扩展性⽽设计的统⼀的、分布式的存储系统。可同时提供三种接⼝:
Object:也称为基于对象的存储,其中的文件被拆分成多个部分并散布在多个存储服务器,在对象存储中,数据会被分解为称为“对象”的离散单元,并保存在单个存储库中(存储到数据文件的某一行,非关系型数据库表文件数据的存储机制),而不是作为文件夹中的文件或服务器上的块来保存,对象存储需要一个简单的HTTP 应用编程接口(API),以供大多数客户端(各种语言)使用。有原⽣的API,⽽且也兼容Swift和S3的API。
Block:需要格式化,将文件直接保存到磁盘上。⽀持精简配置、快照、克隆。
File:提供数据存储的接口,是由操作系统针对块存储的应用,即由操作系统提供存储接口,应用程序通过调用操作系统将文件保存到块存储进行持久化。Posix接⼝,⽀持快照。
(1)对象存储:也就是通常意义的键值存储,其接口就是简单的GET、PUT、DEL 和其他扩展,代表主要有 Swift 、S3 以及 Gluster 等。
(2)块存储:这种接口通常以 QEMU Driver 或者 Kernel Module 的方式存在,这种接口需要实现 Linux 的 Block Device 的接口或者 QEMU 提供的 Block Driver 接口,如 Sheepdog,AWS 的 EBS,青云的云硬盘和阿里云的盘古系统,还有 Ceph 的 RBD(RBD是Ceph面向块存储的接口)。在常见的存储中 DAS、SAN 提供的也是块存储。
(3)文件系统存储:通常意义是支持 POSIX 接口,它跟传统的文件系统如 Ext4 是一个类型的,但区别在于分布式存储提供了并行化的能力,如 Ceph 的 CephFS (CephFS是Ceph面向文件存储的接口),但是有时候又会把 GlusterFS ,HDFS 这种非POSIX接口的类文件存储接口归入此类。当然 NFS、NAS也是属于文件系统存储。
ceph存储具备高性能、高可用性、高扩展特性、特性丰富:
高性能:
(1)摒弃了传统的集中式存储元数据寻址的⽅案,采⽤CRUSH算法,数据分布均衡,并⾏度⾼。
(2)考虑了容灾域的隔离,能够实现各类负载的副本放置规则,例如跨主机、跨机房、机架感知等。
(3)能够⽀持上千个存储节点的规模,⽀持TB到PB级的数据。高可用性:
(1)副本数可以灵活控制 (2)⽀持故障域分隔,数据强⼀致性
(3)多种故障场景⾃动进⾏修复⾃愈 (4)没有单点故障,⾃动管理⾼可扩展性:
(1)去中⼼化 (2)扩展灵活 (3)随着节点增加⽽线性增⻓
特性丰富:
(1)⽀持三种存储接⼝:块存储、⽂件存储、对象存储。
(2)⽀持⾃定义接⼝,⽀持多种语⾔驱动。
ceph的基本架构:
一个ceph集群包含:(1)若干的Ceph OSD(对象存储守护程序);(2)至少需要一个Ceph Monitors 监视器(1,3,5,7...);(3)两个或以上的Ceph 管理器managers (4)运行Ceph 文件系统客户端时,还需要高可用的Ceph Metadata Server(文件系统元数据服务器)。
RADOS cluster: 由多台host 存储服务器组成的ceph 集群【Reliable Autonomic Distributed Object Store 即可靠的、自动化的、分布式的对象存储系统】;RADOS是ceph存储集群的基础。在ceph中,所有数据都以对象的形式存储,并且无论什么数据类型,RADOS对象存储都将负责保存这些对象。RADOS层可以确保数据始终保持一致。
OSD(Object Storage Daemon):每台存储服务器的磁盘组成的存储空间
Mon(Monitor):ceph 的监视器,维护OSD 和PG 的集群状态,一个ceph 集群至少要有一个mon,可以是一三五七等等这样的奇数个。
Mgr(Manager):负责跟踪运行时指标和Ceph 集群的当前状态,包括存储利用率,当前性
能指标和系统负载等。
ceph 是一个对象(object)式存储系统,它把每一个待管理的数据流(文件等数据)切分为一到多个固定大小(默认4 兆)的对象数据,并以其为原子单元(原子是构成元素的最小单元)完成数据的读写。 对象数据的底层存储服务是由多个存储主机(host)组成的存储集群,该集群也被称之为RADOS(reliable automatic distributed object store)存储集群,即可靠的、自动化的、分布式的对象存储系统。 librados 是RADOS 存储集群的API,支持C/C++/JAVA/python/ruby/php/go等编程语言客户端。
librados:librados库,为应用程度提供访问接口。同时也为块存储、对象存储、文件系统提供原生的接口。
RADOSGW:网关接口,提供对象存储服务。它使用librgw和librados来实现允许应用程序与Ceph对象存储建立连接。并且提供S3 和 Swift 兼容的RESTful API接口。
RBD:块设备,它能够自动精简配置并可调整大小,而且将数据分散存储在多个OSD上。
CephFS:Ceph文件系统,与POSIX兼容的文件系统,基于librados封装原生接口。
集群结构功能描述
Monitor(ceph-mon) ceph 监视器: 在一个主机上运行的一个守护进程,用于维护集群状态映射(maintains maps of the cluster state),比如ceph 集群中有多少存储池、每个存储池有多少PG 以及存储池和PG的映射关系等, monitor map, manager map, the OSD map, the MDS map, and the CRUSH map,这些映射是Ceph 守护程序相互协调所需的关键群集状态,此外监视器还负责管理守护程序和客户端之间的身份验证(认证使用cephX 协议)。通常至少需要三个监视器才能实现冗余和高可用性。监视器维护集群状态的多种映射,同时提供认证和日志记录服务,包括有关monitor 节点端到端的信息,其中包括 Ceph 集群ID,监控主机名和IP以及端口。并且存储当前版本信息以及最新更改信息,通过 "ceph mon dump"查看 monitor map。
Managers(ceph-mgr)的功能:在一个主机上运行的一个守护进程,Ceph Manager 守护程序(ceph-mgr)负责跟踪运行时指标和Ceph 集群的当前状态,包括存储利用率,当前性能指标和系统负载。Ceph Manager 守护程序还托管基于python 的模块来管理和公开Ceph 集群信息,包括基于Web的Ceph 仪表板和REST API。高可用性通常至少需要两个管理器。
Ceph OSDs(对象存储守护程序ceph-osd):即对象存储守护程序,但是它并非针对对象存储。提供存储数据,操作系统上的一个磁盘就是一个OSD 守护程序。是物理磁盘驱动器,将数据以对象的形式存储到集群中的每个节点的物理磁盘上。OSD负责存储数据、处理数据复制、恢复、回(Backfilling)、再平衡。完成存储数据的工作绝大多数是由 OSD daemon 进程实现。在构建 Ceph OSD的时候,建议采用SSD 磁盘以及xfs文件系统来格式化分区。此外OSD还对其它OSD进行心跳检测,检测结果汇报给Monitor。通常至少需要3 个Ceph OSD 才能实现冗余和高可用性。
MDS(ceph 元数据服务器ceph-mds):Ceph 元数据,主要保存的是Ceph文件系统(NFS/CIFS)的元数据。注意:ceph的块存储和ceph对象存储都不需要MDS。
Ceph 的管理节点:1.ceph 的常用管理接口是一组命令行工具程序,例如rados、ceph、rbd 等命令,ceph 管理员可以从某个特定的ceph-mon 节点执行管理操作
2.推荐使用部署专用的管理节点对ceph 进行配置管理、升级与后期维护,方便后期权限管理,管理节点的权限只对管理人员开放,可以避免一些不必要的误操作的发生。
ceph节点逻辑结构
pool:存储池、分区,存储池的大小取决于底层的存储空间。
PG(placement group):一个pool 内部可以有多个PG 存在,pool 和PG 都是抽象的逻辑概念,一个pool 中有多少个PG 可以通过公式计算。
OSD(Object Storage Daemon,对象存储设备):每一块磁盘都是一个osd,一个主机由一个或多个osd 组成。
ceph 集群部署好之后,要先创建存储池才能向ceph 写入数据,文件在向ceph 保存之前要先进行一致性hash 计算,计算后会把文件保存在某个对应的PG 的,此文件一定属于某个pool 的一个PG,在通过PG 保存在OSD 上。数据对象在写到主OSD 之后再同步对从OSD 以实现数据的高可用。
ceph数据写入流程
第一步: 计算文件到对象的映射:
File放到ceph集群后,先把文件进行分割,分割为等大小的小块,小块叫object(默认为4M);计算文件到对象的映射,假如file 为客户端要读写的文件,得到oid(object id) = ino + ono
ino:inode number (INO),File 的元数据序列号,File 的唯一id。ono:object number (ONO),File 切分产生的某个object 的序号,默认以4M 切分一个块大小。
比如:一个文件FileID为A,它被切成了两个对象,一个对象编号0,另一个编号1,那么这两个文件的oid则为A0与A1。
1)由Ceph集群指定的静态Hsah函数计算Object的oid,获取到其Hash值。
2)将该Hash值与mask进行与操作,从而获得PG ID。
第二步:通过hash 算法计算出文件对应的pool 中的PG:
小块跟据一定算法跟规律,算法是哈希算法,放置到PG组里。
通过一致性HASH 计算Object 到PG, Object -> PG 映射hash(oid) & mask-> pgid
第三步: 通过CRUSH 把对象映射到PG 中的OSD:
再把PG放到OSD里面。
通过CRUSH 算法计算PG 到OSD,PG -> OSD 映射:[CRUSH(pgid)->(osd1,osd2,osd3)]
第四步:PG 中的主OSD 将对象写入到硬盘。
第五步: 主OSD 将数据同步给备份OSD,并等待备份OSD 返回确认。
第六步: 备份OSD返回确认后,主OSD 将写入完成返回给客户端。
Ceph中数据写入,会有三次映射
(1)File -> object映射
(2)Object -> PG映射,hash(oid) & mask -> pgid
(3)PG -> OSD映射,CRUSH算法
CRUSH算法介绍
CRUSH,Controlled Replication Under Scalable Hashing,它表示数据存储的分布式选择算法, ceph 的高性能/高可用就是采用这种算法实现。CRUSH 算法取代了在元数据表中为每个客户端请求进行查找,它通过计算系统中数据应该被写入或读出的位置。CRUSH能够感知基础架构,能够理解基础设施各个部件之间的关系。并CRUSH保存数据的多个副本,这样即使一个故障域的几个组件都出现故障,数据依然可用。CRUSH 算是使得 ceph 实现了自我管理和自我修复。
Ceph 使用CRUSH 算法来准确计算数据应该被保存到哪里,以及应该从哪里读取,和保存元数据不同的是,CRUSH 按需计算出元数据,因此它就消除了对中心式的服务器/网关的需求,它使得Ceph 客户端能够计算出元数据,该过程也称为CRUSH 查找,然后和OSD 直接通信。
(1)如果是把对象直接映射到OSD 之上会导致对象与OSD 的对应关系过于紧密和耦合,当OSD 由于故障发生变更时将会对整个ceph 集群产生影响。
(2).于是ceph 将一个对象映射到RADOS 集群的时候分为两步走:(a)首先使用一致性hash 算法将对象名称映射到PG (b)然后将PG ID 基于CRUSH 算法映射到OSD 即可查到对象
(3)以上两个过程都是以”实时计算”的方式完成,而没有使用传统的查询数据与块设备的对应表的方式,这样有效避免了组件的”中心化”问题,也解决了查询性能和冗余问题。使得ceph集群扩展不再受查询的性能限制。
(4)这个实时计算操作使用的就是CRUSH 算法(Controllers replication under scalable hashing) 可控的、可复制的、可伸缩的一致性hash算法。
CRUSH 是一种分布式算法,类似于一致性hash 算法,用于为RADOS 存储集群控制数据的分配。
对象存储与文件存储:文章来源:https://www.toymoban.com/news/detail-469816.html
文件存储和对象存储底层都是块存储,但是文件存储在管理文件上是文件树,对象存储是扁平化的小文件存储,管理上不能单单靠文件树结构 文章来源地址https://www.toymoban.com/news/detail-469816.html
到了这里,关于分布式数据(文件)存储的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!