1. 数据与元数据
现代文件系统内,文件的内容和属性是分开放置的。文件的属性信息,例如文件创建/最后更改时间,读写权限及所有者信息,以及数据块的物理分布信息等,又被称作元数据(metadata)。为了提高性能和可靠性,文件系统内的元数据往往是集中放置集中管理的,例如NTFS上的MFT,或者EXT系列的inode等。
如果说数据本身是一个文件的肉身的话,文件对应的元数据就是这个文件的魂魄。为了提高性能,操作系统日常的删除文件操作仅仅是丢弃了对应文件的元数据而已,以这种方法删除的文件是可以重建被删除文件的元数据来还魂的。没错,陈老师当年就是这么翻车的。
2. 写时复制文件系统
所谓写时复制(CopyonWrite,CoW)在存储上一般指先写肉身,再赋予魂魄的操作逻辑。虽然实际上所有现代文件系统实际上都是这么操作的,但真正算得上CoW文件系统的同学们还能更进一步支持更精细的元数据操作,例如克隆与去重等,下面再详细介绍。
3. 软链接、硬链接、克隆和去重
要得到一份文件的复制品办法很多,除了重新拷贝一份外还可以制作软硬链接或者克隆一份。但这几个操作是有本质区别的:
软链接:Windows上的mklink/D命令和Linux上的ln-s命令,创建的是文件的软链接。软链接本质上本身就是一个指向目标文件的特殊指针文件。目标文件被删掉后,软链接还在,只不过指向的目标没了。是的,这就是个快捷方式。
硬链接:同一个文件被多次引用的时候,后来被引用出来的那几份就可以被认为是最初那个初始文件的硬链接。就是说,魂魄还是那个魂魄,然而这个魂魄是个戏精,同一个魂魄有好几个身份……我们知道在Linux眼中一切都是文件,就连目录其实也是一种文件。一个空目录,初始的引用数就是2,这个2是怎么来的呢?其实就是目录本身($pwd)和其内部指向自己的那个.($pwd/.)
就是说,一个目录在出生那一刻就已经有俩身份证了。
对了,每个目录下天生除了那个指向自己的”.”外,还有一个指向上一级目录的”..”。这也会增加父目录的引用数。聪明的同学马上就能意识到,图中test目录本身4个引用数,减去天生指向自己的那俩,剩下的2实际体现的就是子目录数量(等于子目录里面的”..”指向其本身的数量)
有目录这个例子,硬链接的特性也很清楚了,目标文件和硬链接就是同一个东西拿着不同的身份证而已,所以两者是同生共死的,连文件属性都是一模一样(毕竟连元数据都是共用的)。
克隆:软硬链接都是传统文件系统就能提供的基本功能,但克隆就必须要CoW文件系统才能实现了,因为克隆这个动作是复制了一份新的元数据指向同一份数据,就是说同一个肉身附上了俩魂魄,这下厉害了,真·精神分裂。
精神分裂总是很有意思的,下面我就来演示一番,在/nfs_srv/images这个btrfs卷下所有linux开头的文件实际大小总共5.8G(稀疏文件,实际上每个文件都是500G),我把所有这些文件克隆一份到/nfs_srv/images/ballast里去:
5.8G文件的克隆过程只用了5.5秒,这还是在慢得伤心的土炮虚拟机里。更重要的是,这个卷并没有在文件克隆后用掉更多空间。
文件被克隆后,源文件A和克隆体A’虽然用着相同的肉身,但是两者在逻辑上已经是两个东西了。两者可以分别被改写而不互相影响。直观点说,A’动胳膊的时候就会生成一个新胳膊,转脑袋的时候就会生成一个新脑袋,全身都动起来的时候就不再和当初的A共用任何肉身了。
相比文件克隆,在CoW文件系统上卷级别的克隆其实更加常见,这就是传说中的snapshot。例如ZFS和WAFL的snapshot(虽然这俩的snapshot默认都是只读的。ZFS上的可写卷克隆就叫clone以区别于默认的snapshot,而ZFS上的文件克隆一直到今年放出的Solaris 11.4beta里的ZFS v43才正式提供。倒是Btrfs上的子卷snapshot默认就是可写的)
4. 块级去重(blockleveldeduplication)
细心的读者刚才可能已经注意到了,光是被我克隆的文件加起来明明已经有5.8G了,然而整个卷的空间总占用咋才1.5G呢?这不科学!
其实这还真挺科学的,咱们一步步看。所有linux开头的文件其实都克隆自文件模版,也就是那几个disksource开头的文件,它们在有任何改写前都没有实际占用存储空间。
于是又有人说“还是不对啊,这仨模版加起来也快3G了,怎么还是比实际使用空间大了快一倍呢?”
这是因为三个模版的内容都是不同版本的Linux内核的源文件,虽然总体互有不同,但实际上还是有很多内容是重复的,重复部分占用的空间被文件系统的去重功能给回收掉了。
在CoW文件系统上,块级去重的过程挺类似于反向的文件克隆——当文件系统发现不同文件使用的块内容完全相同时,就会将所有文件使用的块指向其中一个,然后丢弃掉其余的重复块以释放空间。按之前那个比喻的话就是我和某君C被发现右手完全一样,于是我们俩以后就用同一个右手了,多出来的那个右手就被砍了扔掉减肥……(好消息是如果C君从此发愤图强导致右手发生了彻底的变化的话就会得到一个新右手,也就不用凑合着和我共用了。)
5. 远程文件克隆(remotefileclone)与服务器侧拷贝(serversidecopy)
刚才说的都是本地文件系统的事情,但当使用的存储资源来自存储服务器的时候(例如NFS或者Samba共享),还能不能实现文件克隆呢?经过一系列的测试,我的答案是:能。至少在Ubuntu18.04通过NFSv4.2共享的Btrfs卷是支持远程文件克隆命令的。NetApp的ONTAP8.3也支持这个功能,还给起了个专门的名字叫FlexClone。
说到NFSv4.2,里面还提供了个很有意义的功能叫做serversidecopy,意思是客户端只发送拷贝指令而不是拷贝内容到NFS服务端,实际的拷贝动作直接在服务端内部的本地文件系统完成(传统方式还真是傻乎乎的先由客户端读文件内容再原样扔回服务端这么绕一圈拷贝的),直接上个图就很清楚了。
另外再插一句,Samba也在4.7版本后支持serversidecopy了。
6. 结语
扯了一大堆最后上个表吧,目前我已经测试的功能支持列表大概是这个样子的。
某种意义上说自己搭建的土炮Linux存储服务器至少在功能上并不见得会比NetApp弱。至于可靠性和勤务性,无论你在设备上花了多少钱,可靠性和勤务性其实更多取决于合理的规划与设计。这也算是开源项目的一个小小的胜利……吧
| 留言与评论(共有 0 条评论) |