很多人容易将分布式存储和分布式文件系统的概念搞混,我先做一个概念上的梳理:
分布式存储所涵盖的范围极广,例如NFS,虽然只是用于目录共享的网络文件系统,但是它也属于分布式存储范畴,再比如说分布式对象存储,例如Ceph体系不仅包括了分布式文件系统CephFS,也包括了Ceph分布式对象存储,它们都属于分布式存储范围。
分布式文件系统(DFS)最关键的一个特征就是模拟了本地文件系统的目录层次,这对于文件在虚拟目录中的移动,管理具有很好的优势,首先这个优势是分布式对象存储等无法做到的。
我们本文主要是聊聊分布式文件系统里面的去中心化架构的开源产品GlusterFS
我们先简单看看GlusterFS在CentOS上的安装:
#安装gluster源 yum install centos-release-gluster #客户端安装 yum install glusterfs glusterfs-fuse #服务端安装 yum install glusterfs-server #加入CentOS自启动 systemctl enable glusterd.service #启动GlusterFS systemctl start glusterd.service #在bigdata-001,bigdata-002,bigdata-003三个节点都安装好GlusterFS后 #在bigdata-001上探测其他节点加入集群 gluster peer probe bigdata-002 gluster peer probe bigdata-003 #查看Gluster集群状态 gluster peer status
我们再返回头专门说分布式文件系统(DFS)的问题:
1. 解决副本存储占用率问题
先说数据可靠性问题,副本因子为3个副本,这在不少的DFS系统中作为默认副本数量,这只是数据可靠性的一种策略,通过3副本的形式,提升数据可靠性,本质上就是提升了分布式环境数据的容错率,但是3副本最大的问题就是占空间,DFS集群的空间利用率只有33.3%,这么低的利用率显然不符合一些场景,例如长期的冷数备份。
那么DFS有没有更好的空间利用方式呢?有!目前比较成熟的方案就是纠删码(EC冗余),类似Raid5,Raid6。
我们拿其中一种分布式文件系统GlusterFS来探其原理,看看它是怎么通过纠删码解决的:
首先数据写文件的时候被分成N个组块(chunk),每个chunk又被切成N个条(stripe),如果分布式环境有三个存储节点(bricks),那么就把stripe切成2个块(block),然后再根据这2个block计算出1个校验块,然后这3个块分别存储在3个bricks。数据条就这么依次轮询的方式,将校验块的位置轮换存储在不同brick上,这样校验块的分布可以更均匀。
#创建分散片,3个disperse,3个Bricks其中1个redundancy,1(组)x(2+1)=3 利用率66.7% gluster volume create gv3 disperse 3 redundancy 1 transport tcp bigdata-001:/opt/gfs-data4 bigdata-002:/opt/gfs-data4 bigdata-003:/opt/gfs-data4 force
其次当从文件读数据时,每次只从两个bricks中各取出1个块,如果这两个block都是数据块,那么就成功拿到chunk里的一个数据条,如果有一个是校验块,那么就能通过校验块和一个数据block计算出另一个数据block,完成数据条的组合。这种情况下,即便是3个bricks节点有1个brick宕机了,另外两个bricks也能通过校验码计算完成数据恢复,这就是GlusterFS利用纠删码技术实现数据冗余的原理。
通过这种方式,我们就比2副本50%,3副本33.3%的多副本模式要省空间,最少可以达到66.7%的磁盘利用率。但是其问题是特别消耗CPU计算,上面那种读取情况,三分之二的读取数据条时间都要进行校验码计算。因此可以利用Intel CPU推出的ISA-L底层函数库专门用于提升校纠删码算法的编解码性能。通常情况下,EC冗余策略用于冷数据的备份,也就是不经常访问,但又必须联机存储以备查询的数据。
除了磁盘利用率,多副本方式用空间换效率的方式肯定是最好的,从性能考虑是没什么问题。
唯一一点需要注意的是GlusterFS是去中心化的DFS架构,其文件目录的管理操作不如其他中心化DFS架构容易,例如Hadoop HDFS架构都是基于NameNode的主节点通过对元数据的操作,实现各个节点的数据文件的逻辑变化,但GlusterFS不行,需要客户端来主导管理性操作,但最终都会触发不同节点的数据文件发生物理上的变动。
尽管HDFS也有EC方案,但并没有GlusterFS的EC策略灵活方便,GlusterFS很容易就能形成ES策略与其他策略在同一集群的共用,也支持分布式卷+EC卷=分布式EC卷的架构灵活组合。
2. 解决复杂的高可用问题
传统分布式文件管理存在对元数据的高度依赖问题,HDFS的大量数据存储节点DataNode,需要依赖元数据服务NameNode的统一管理,MooseFS的大量数据存储节点ChunkServer需要依赖元数据服务MFS Master,任何客户端发起对数据存储节点的写入和查询,都需要从元数据服务节点获取路径,或者获取写入管道的分配。
这种依赖元数据服务的架构,极为突出的问题就是元数据服务不能挂,一旦元数据挂了,那么整个集群就停摆了,所谓单点故障导致的灾难。
因此HDFS为NameNode引入了高可用(HA)架构,相当于双节点主备关系,中间的元数据需要QJM机制来保证同步,ZKFC服务来监控主备节点的状态,我们掐指一算,NN Active、NN Standby、Journal集群、ZKFC监控双节点、ZooKeeper集群,五种角色的服务或者集群来保证元数据架构的高可用,非常的复杂。
MooseFS甚至对于高可用版本只存在于商业版本,而只是给开源版本采用了类似MySQL的主从机制,一个MFS Master连接多个MFS MetaLogger,只实现了元数据的主从复制,满足Master宕机后,可以在其他MetaLogger节点手动启动Master读取备份的元数据。但是没有商用版的高可用支持,开源版本就无法达到故障转移的运行可靠性,因此MFS Master挂了,集群肯定就不好了,开源版本无法作为严格性要求高的生产环境,需要达到就请付费了。
我们看到了分布式文件系统因为对元数据的高度依赖,形成了对高可用环境的高度需求,高可用环境又导致了部署复杂度,甚至干脆收费。
那么有没有更好的办法呢?这个问题还是GlusterFS做的比较独树一帜,直接抛弃了传统分布式文件系统的元数据集中式管理,大家想,为什么能在一个集群成百上千台机器之上构建出一个虚拟的文件目录形式?这是因为全靠集群元数据的组织与管理,我们读取的目录,实际上只是元数据在内存中的一个组织树结构而已。
作为GlusterFS到好,直接废了这种元数据集中管理的架构,而是采用了思想更为超前的去中心化架构。任何一个节点都是对等的,每个节点的目录属性里面存储了自己的元数据,大家通过共识机制,而非管理机制,那么客户端只需要遵循共识机制来访问集群的数据节点,可以这么讲,客户端这时候即当妈又当爹,被设计得非常重,集数据读写、查询和组织管理为一身。
GlusterFS用卷(Volume)的逻辑概念,适配了分布式的不同架构,例如:分布式卷,集群不同存储节点但完全相同路径的目录被Hash成多个段,文件写入的时候,客户端计算文件的Hash值,就能确定这个文件应该存储的路径目录属于集群那个节点的Hash范围,客户端就存储到那个节点上的目录,这样就实现了大量写入文件在集群多个存储节点的相同路径目录的分布存放。
GlusterFS还支持复制卷,也就是一对三的文件复制模式,甚至还支持分布式副本卷这样的卷卷嵌套模式。总之GlusterFS想通过去中心这种方式,避开传统分布式文件系统的因为单点故障而高度依赖的高可用架构所带来的复杂度。
#GlusterFS创建3副本模式,分别在三个bricks节点的/opt/gfs-data2目录作为副本卷的存储目录 gluster volume create gv1 replica 3 transport tcp bigdata-001:/opt/gfs-data2 bigdata-002:/opt/gfs-data2 bigdata-003:/opt/gfs-data2 bigdata-004:/opt/gfs-data2 force
不过去中心化也有去中心化的问题,在文件的操作管理上始终不如集中式的灵活,并且元数据的操作GlusterFS倾向于物理行为,而集中式都是逻辑行为,因此GlusterFS才会出现在移动文件操作的时候,竟然在不同节点做分布式文件链接这样通过策略解决架构缺陷的蹩脚手法。当然这样完全可以理解,没有十全十美的事情。
但是GlusterFS作为去中心化架构,这种优势就是将所有节点的重要级别拉平了,那么就不存在那个节点是最重要的问题,任何节点都可以故障,但不会影响到集群整体的高可靠性,这是去中心化架构一直以来最具有优势的传统。