Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1086289
  • 博文数量: 143
  • 博客积分: 969
  • 博客等级: 准尉
  • 技术积分: 1765
  • 用 户 组: 普通用户
  • 注册时间: 2011-07-30 12:09
文章分类

全部博文(143)

文章存档

2023年(4)

2021年(2)

2020年(4)

2019年(4)

2018年(33)

2017年(6)

2016年(13)

2014年(7)

2013年(23)

2012年(33)

2011年(14)

我的朋友

分类: AIX

2013-06-07 23:33:03

像ext3/4这种支持POSIX标准接口的文件系统,基本都实现在内核态,即位于内核中VFS的下一层(除非采用FUSE那样的机制,能在用户态实现)。这种经典的文件系统往往由于考虑太多功能需求和接口标准,无法应对互联网海量文件存储在性能和伸缩上的要求,因此也就涌现了像google的GFS和hadoop的HDFS这样的基于用户态的分布式文件存储系统,其实这类文件系统应该称为No-POSIX文件系统,因为No-SQL系统其实是相对于SQL-based的DBMS而言的(后续都称No-Posix)。下面介绍一种应用于互联网的No-Posix分布式文件系统的块存储实现(由于本主题只分析块存储实现,所以对于其他层次的东西暂时忽略)。

        首先看看该文件系统是如何对硬盘进行管理的,其on disk结构图如下:

        看这个图,跟一般的文件系统(比如ext3)对硬盘的管理有点相似,但它是直接在块设备文件(比如/dev/sdb)上构建的,在用户态通过libc的IO函数读写块设备文件来存储文件数据(并没有在块设备上建立任何内核中已经注册的文件系统)。除了前面4K的disk head是为了兼容系统对硬盘引导块的需求以外(基本无用),剩下的空间被被划分为多个等同大小的CHUNK块。每个CHUNK块里面主要由binlog section和data section构成。binlog section其实是存放了大量的inode变更记录,每次inode的增加、删除、修改都会相应在binlog中写入一条记录(因此binlog section的大小也限制了inode的个数)。但是这里的inode其实并不是像ext3文件系统中的文件inode,这里的inode只是描述CHUNK里面一片文件数据的元数据所形成的inode(实际这样一个inode的空间只有二三十个字节,比ext3的128字节的inode相差甚远)。而data section则是存储真正文件数据片的区域。这里可以看到,CHUNK里面是没有专门的像ext3那样的inode table区域的,因为inode只有in memory形态(机器故障恢复或者进程重启,都需要从binlog中恢复内存中的inode表)。

        CHUNK是整个文件系统的基本存储空间分配单元,大量位于不同机器上不同硬盘的CHUNK构成了整个文件系统可用的存储空间,而CHUNK之间可以互相配对,形成应用态的Raid1存储。(一个用户角度的文件实际上被划分为多个数据片,一般按照某个定长来划分,这些数据片可以存储在不同的CHUNK上,用户读取文件的时候,通过一个文件索引层找出这些数据片所在的CHUNK,然后再访问这些CHUNK来读取数据)

        虽然一个CHUNK的on disk结构很简单,但是其in memory结构相比稍微复杂一点点,也只有这样才能在性能上有提升,否则什么都跟硬盘映射起来,两者的数据一致性同步的代价是挺高的。下面看一个CHUNK的in memory结构:

        一个CHUNK由一个chunk inode来描述(实际上chunk inode也只有in memory形态)。chunk inode主要使用inode hash table来管理属于本CHUNK的inode。简单的inode构造和hash table实现也注定了它不是传统意义上的文件系统,平坦而无序,更接近key-value式存储。每个chunk inode有一个offset变量表明其data section的已使用区间位置(由于每个CHUNK大小一样,所以offset大小也决定了CHUNK剩余空间的大小,从而可以利用这个指标来进行负载均衡,使得每个CHUNK的剩余空间都差不多)。而数据片的inode主要是保存了一个offset和length,分别表示该数据片在CHUNK里的偏移量和数据片长度,理论上说这样的访问效率会比较高。每个CHUNK都是以append的方式在不断增长,即使数据片删除了,也不会立即回收空间,只是对inode做一个标志。

如果很少删除,那么这种方式其实是挺好的,但是如果删除很频繁,那么每个CHUNK已使用区间会有很多空洞而不能重复利用,这是一个主要弊端。解决方法其实有很多,一个是修改算法使得inode和空洞能重用,另一个方法就是定期对整个CHUNK进行pack操作(此时需要暂时屏蔽对该CHUNK的读写访问),使得空洞全部转移到尾部的未使用区间,而且重新整理binlog section。当然,前面说到这里的CHUNK里面的数据片inode并不是代表真正的文件,所以该分布式文件系统还需要有一层分布式的索引层(索引层是否分布式并不重要,像GFS和HDFS则是集中式的,由master或name node来管理)来表示真正的用户角度的文件,这个索引层本身采用的是典型的key-value存储。相对来说,数据量至少降低2-3个数量级。

对比传统的文件系统(比如ext3),这类No-Posix的分布式文件系统,其实是大大简化了底层的存储块分配与读写机制,同时在元数据上也尽量节省,只要够用就行(更多的扩展性放到了更高的层次去解决)。其次,在数据一致性和数据恢复方面,在存储层这一级别也是比较轻量级的,起码没有像jbd这样重的机制。再次,这类No-Posix的分布式文件系统通过在应用层次的N份镜像存储,来规避单机可靠性较低,以得到较高的整体可用性。传统文件系统更多的是考虑到磁盘空间的利用率,比如如何重复利用磁盘空间(比如文件的覆盖写),如何对文件的并发读写进行同步互斥等等,这些在No-Posix的分布式文件系统里面基本都弱化了,往往采用的是append的方式来提升写速度,通过多CHUNK的并发读来提升读速度,通过上层限制并发写来维护数据一致性等等。最后,对于这种No-Posix的分布式文件系统而言,其实索引的组织并不是最关键的,往往简单的哈希分布已经足够,通过在多个机器间分摊计算量来达到较好的性能,而传统的单机文件系统往往需要考虑较复杂的索引组织结构来提升性能(比如遍历目录文件),因为单机容易出现性能瓶颈。

当然,对于No-Posix的分布式文件系统来说,其实也是可以在上层实现有限的Posix接口,只是这种实现往往牺牲了效率。对于传统单机文件系统,比如btrfs,zfs等已经达到了一个非常高的水平。而像ceph这类比较激进的分布式文件系统,既能实现Posix接口,又能高效利用btrfs等作为存储节点的文件系统,也许是一个比较好的结合点。

阅读(3428) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~