分布式存储已经研究很多年,但直到近年来,伴随着谷歌、亚马逊和阿里等互联网公司云计算和大数据应用的兴起,它才大规模应用到工程实践中。如谷歌的分布式文件系统GFS、分布式表格系统google Bigtable,亚马逊的对象存储AWS,阿里的TFS等都是很好的代表,同时也催生了一大批优秀的开源分布式存储系统,包括ceph、swift、Lustre和glusterfs等。
分布式存储系统
分布式存储按其存储接口分为三种:文件存储、块存储和对象存储。
文件存储
通常支持POSIX接口(如glusterfs,但GFS、HDFS是非POSIX接口的),可以像普通文件系统(如ext4)那样访问,但又比普通文件系统多了并行化访问的能力和冗余机制。主要的分布式文件存储系统有TFS、cephfs、glusterfs和HDFS等。主要存储非结构化数据,如普通文件、图片、音视频等。可以采用NFS和CIFS等协议访问,共享方便。NAS是文件存储类型。
块存储
这种接口通常以QEMU Driver或者Kernel Module的方式存在,主要通过qemu或iscsi协议访问。主要的块存储系统有ceph块存储、sheepdog等。主要用来存储结构化数据,如数据库数据。数据共享不方便。DAS和SAN都是块存储类型。
对象存储
对象存储系统综合了NAS和SAN的优点,同时具有SAN的高速直接访问和NAS的数据共享等优势。以对象作为基本的存储单元,向外提供RESTful数据读写接口,常以网络服务的形式提供数据访问。主要的对象存储系统有AWS、swift和ceph对象存储。主要用来存储非结构化数据。
Glusterfs
Glusterfs是一个开源分布式文件系统,具有强大的横向扩展能力,可支持数PB存储容量和数千客户端,通过Infiniband RDMA 或Tcp/Ip 方式将许多廉价的x86 主机,通过网络互联成一个并行的网络文件系统。具有可扩展性、高性能、高可用性等特点。
GlusterFS采用可堆叠的用户空间设计,如图所示:
imageglusterfs堆栈式结构
Glusterfs是根据fuse提供的接口实现的一个用户态的文件系统,主要包括gluster、glusterd、glusterfs和glusterfsd四大模块组成:
- gluster:是cli命令执行工具,主要功能是解析命令行参数,然后把命令发送给glusterd模块执行。
- glusterd:是一个管理模块,处理gluster发过来的命令,处理集群管理、存储池管理、brick管理、负载均衡、快照管理等。集群信息、存储池信息和快照信息等都是以配置文件的形式存放在服务器中,当客户端挂载存储时,glusterd会把存储池的配置文件发送给客户端。
- glusterfsd:是服务端模块,存储池中的每个brick都会启动一个glusterfsd进程。此模块主要是处理客户端的读写请求,从关联的brick所在磁盘中读写数据,然后返回给客户端。
- glusterfs:是客户端模块,负责通过mount挂载集群中某台服务器的存储池,以目录的形式呈现给用户。当用户从此目录读写数据时,客户端根据从glusterd模块获取的存储池的配置文件信息,通过DHT算法计算文件所在服务器的brick位置,然后通过Infiniband RDMA 或Tcp/Ip 方式把数据发送给brick,等brick处理完,给用户返回结果。存储池的副本、条带、hash、EC等逻辑都在客户端处理。
在使用glusterfs提供的存储服务之前,需要先挂载存储池,向挂载点写数据,会经过fuse内核模块传给客户端,客户端检查存储池的类型,然后计算数据所在服务器 ,最后通过socket或rdma与服务器通信,如图2所示:
glusterfs模块关系图Glusterfs作为一款开源的分布式文件系统,在开源社区的活跃度很高,目前已经被红帽收购,国内外也有大量的用户在研究和应用,相关技术文档很丰富。它并不完美,为了支持线性扩展和高性能,而在小文件性能和元数据性能上做了让步,但却可以满足一定的场景,如大数据应用和视频存储等。
接下来会从优点和缺点两方面入手来介绍glusterfs。
优点
- 无元数据节点性能瓶颈
采用无中心对称式架构,没有专用的元数据服务器,也就不存在元数据服务器瓶颈。元数据存在于文件的属性和扩展属性中。当需要访问某文件时,客户端使用DHT算法,根据文件的路径和文件名计算出文件所在brick,然后由客户端从此brick获取数据,省去了同元数据服务器通信的过程。- 良好的可扩展性
使用弹性hash算法代替传统的有元数据节点服务,获得了接近线性的高扩展性。- 高可用
采用副本、EC等冗余设计,保证在冗余范围内的节点掉线时,仍然可以从其它服务节点获取数据,保证高可用性。采用弱一致性的设计,当向副本中文件写入数据时,客户端计算出文件所在brick,然后通过网络把数据传给所在brick,当其中有一个成功返回,就认为数据成功写入,不必等待其它brick返回,就会避免当某个节点网络异常或磁盘损坏时因为一个brick没有成功写入而导致写操作等待。
服务器端还会随着存储池的启动,而开启一个glustershd进程,这个进程会定期检查副本和EC卷中各个brick之间数据的一致性,并恢复。- 存储池类型
丰富包括粗粒度、条带、副本、条带副本和EC,可以根据用户的需求,满足不同程度的冗余。粗粒度卷不带任何冗余,文件不进行切片,是完整的存放在某个brick上。
条带卷不带任何冗余,文件会切片存储(默认大小为128kB)在不同的brick上。这些切片可以并发读写(并发粒度是条带块),可以明显提高读写性能。该模式一般只适合用于处理超大型文件和多节点性能要求高的情况。
副本卷冗余度高,副本数量可以灵活配置,可以保证数据的安全性。
条带副本卷是条带卷和副本卷的结合。
EC卷使用EC校验算法,提供了低于副本卷的冗余度,冗余度小于100%,满足比较低的数据安全性,例如可以使2+1(冗余度为50%)、5+3(冗余度为60%)等。这个可以满足安全性要求不高的数据。- 高性能
采用弱一致性的设计,向副本中写数据时,只要有一个brick成功返回,就认为写入成功,不必等待其它brick返回,这样的方式比强一致性要快。
还提供了I/O并发、write-behind、read-ahead、io-cache、条带等提高读写性能的技术。并且这些都还可以根据实际需求进行开启/关闭,i/o并发数量,cache大小都可以调整。
缺点
- 扩容、缩容时影响的服务器较多
Glusterfs对逻辑卷中的存储单元brick划分hash分布空间(会以brick所在磁盘大小作为权重,空间总范围为0至232-1),一个brick占一份空间,当访问某文件时,使用Davies-Meyer算法根据文件名计算出hash值,比较hash值落在哪个范围内,即可确定文件所在的brick,这样定位文件会很快。但是在向逻辑卷中添加或移除brick时,hash分布空间会重新计算,每个brick的hash范围都会变化,文件定位就会失败,因此需要遍历文件,把文件移动到正确的hash分布范围对应的brick上,移动的文件可能会很多,加重系统负载,影响到正常的文件访问操作。- 遍历目录下文件耗时
1.Glusterfs没有元数据节点,而是根据hash算法来确定文件的分布,目录利用扩展属性记录子卷的中brick的hash分布范围,每个brick的范围均不重叠。遍历目录时,需要readdir子卷中每个brick中的目录,获取每个文件的属性和扩展属性,然后进行聚合,相对于有专门元数据节点的分布式存储,遍历效率会差很多,当目录下有大量文件时,遍历会非常缓慢。
2.删除目录也会遇到同样的问题。
3.目前提供的解决方法是合理组织目录结构,目录层级不要太深,目录下文件数量不要太多,增大glusterfs目录缓存。另外,还可以设计把元数据和数据分离,把元数据放到内存数据库中(如redis、memcache),并在ssd上持久保存。- 小文件性能较差
1.Glusterfs主要是为大文件设计,如io-cache、read-ahead、write-behind和条带等都是为优化大文件访问,对小文件的优化很少。
2.Glusterfs采用无元数据节点的设计,文件的元数据和数据一起保存在文件中,访问元数据和数据的速率相同,访问元数据的时间与访问数据的时间比例会较大,而有元数据中心的分布式存储系统,对元数据服务器可以采用更快速的ssd盘,可以采用更大的元数据缓存等优化措施来减小访问元数据时间与访问数据时间的比值,来提高小文件性能。
3.Glusterfs在客户端采用了元数据缓存md-cache来提高小文件性能,但是md-cache大小有限,但在海量小文件场景下,缓存命中率会严重下降,优化效果会减小,这就需要增大元数据缓存。
4.针对小文件性能差的问题,也可以参考TFS的做法, TFS会将大量的小文件合并成一个大文件,这个大文件称为Block,每个Block拥有在集群内唯一的编号(Block Id),Block Id在NameServer创建Block时分配,NameServer维护block与DataServer(存储Block的实际数据)的关系。
网友评论