文件系统管理及调优
目录的索引记录了该目录下包含的文件名。
通常,我们删除一个文件只是删除了这个文件的inode 索引,并不会删除block 区域的内容,当有新的数据需要写入时则覆盖。
在同一个文件系统中移动文件本质上是移动inode 数据,它指向的block 区域数据并没有产生变化。
如果是跨分区、跨磁盘、或跨文件系统移动数据,就会移动inode 和block 数据。
对于应用程序而言,只要有对应文件系统的驱动,就可以通过系统调用访问虚拟文件系统。
文件系统格式化的本质为分区划分索引区和数据块区的过程。
这条命令看到的内容其实就是文件系统的元数据。
文件的元数据叫inode,文件系统的元数据叫super block(超级块)
除了tune2fs,还有dumpe2fs 命令可以看到更为详细的文件系统信息。
可以观察到,这个文件系统划分了几个group,每个group 的大小由block 数量决定。
为什么一个文件系统会分多个组呢?
假如说一个文件需要扩容,如果没有划分组,可能扩容时写入的数据距离原来的数据block 区域较远,导致数据严重碎片化,影响读写性能,划分组能在一定程度上减轻这种负面影响。
划分组后,写入数据时,类似上图这种情况,分散到不同的组里面,尽可能地避免文件扩容时从别的组扩。
Inode bitmap 记录了组的inode 区使用情况,Block bitmap 记录了组的block 区使用情况,当有新的数据需要写入时,从bitmap 里面分配空闲的inode 和block 并更新记录,并且每个组汇总数据给superblock,这样就知道了整个文件系统的使用情况。
因为superblock 记录的是文件系统的信息,所以它十分地重要,很多时候,文件系统损坏的原因就是superblock 损坏导致的。因此,在group 0 的第一个block 就是superblock 的数据,group 1 的第一个block 就是backup superblock,给第一个superblock 做了一个备份,第一个superblock 在第0 个block 位置,第二个也就是备份superblock 在第32768 个block 的位置,是固定的,除了group 1 有备份超级块,还有group3/5/7/9,不是仅有一个备份。
ext4 的文件系统格式化完成后,默认在目录底下有一个这样的文件夹,不建议删除该文件夹, 在文件系统损坏时,系统自动就会把一些找到的文件存放到这里面,有一些迁移工具如果检测到该文件夹不存在也会报错终止。
这是模拟文件系统超级块损坏的情况,现在这个文件系统已经不能被挂载了。
如果一个文件系统已经写入到/etc/fstab 开机自动挂载,只要文件系统损坏,那么开机就无法正常启动了,所以很多时候,开机系统无法启动跟文件系统损坏有关联,那么我们就要尝试修复它,使用fsck 命令:
umount /dev/vdb1
fsck /dev/vdb1
它会找到备份的超级块来恢复。
有的时候文件系统可能损坏比较严重,备份超级块也坏了,只是fsck 也无法修复,这个时候就需要手动来恢复了。
e2fsck -b 163840 /dev/vdb1
可以看到已经恢复了,这个163840 是group 5 的备份超级块,位置是固定的。fsck 命令默认只会从group 1 的超级块32768 来尝试恢复,当无法从这个位置恢复时,不会往后面的超级块扫描了。
如果不想手动回复y 确认,可以:
fsck -y /dev/vdb1
以上是ext4 文件系统的修复方法。
而xfs 与之不同。
这个时候就不能用fsck 命令来修复了,xfs 有自己的一套管理体系, 输入xfs 按tab 键补齐看看:
修复xfs 文件系统应该用xfs_repair
xfs_repair /dev/vdc1
这样就修复好了。
xfs 文件系统修复相对来说更智能,不用像ext4 那样指定备份超级块的位置,从工作经验来看,xfs 也更稳定,ext 文件系统出故障的概率更高一些。
哪些情况下,会导致文件系统超级块损坏呢?
- 系统非正常关机
- 在RHEL 6 及以前一些古老的系统上,系统已经运行了很久,即使是正常关机或重启也很有可能导致文件系统损坏
tune2fs -l /dev/vdb1
现在RHEL 8 系统比较智能,这里有一个参数是限制该文件系统最大挂载次数,这里为-1,表示没有上限。
在RHEL 6 系统中,挂载次数到了30 次的时候,就会报文件系统故障,强制让管理员进行修复,还有一个参数是check interval,在RHEL 6 中默认是6 个月,如果6 个月没有进行文件系统扫描了,下次重新挂载就会强制让管理员进行扫描修复。
文件系统还有一类区分:
ext2/fat32:非日志型文件系统
ext3/ext4/xfs/ntfs:日志型文件系统
日志型文件系统最早是IBM AIX 使用的JFS、JFS2 文件系统引申出来的,
JFS 可以在线拉伸,但不能缩小;JFS2 可以在线拉伸和缩小,这个J 就是Journal 的意思。
接下来看日志型文件系统与非日志型文件系统之间的区别:
非日志型文件系统
写入数据中断时,会造成inode 记录与实际block 写入不对称的情况,修复数据需要扫描整个文件系统。
日志型文件系统
日志区一般来说是64M,并不是固定的,按照文件系统大小和一定的比例分配,当写入数据时,先往日志区写inode 数据,然后写block,block 数据写完后最后再往inode 区写数据,如果block 写入时中断,下次开机的时候,日志区的这一部分数据就被删掉,相当于没有往block 里面写数据。
所以日志型文件系统会有两次写索引的动作,这样在写大文件的时候没有什么问题,当有写入大量的小文件时,写inode 这个动作就可能会成为性能瓶颈,这个时候,我们可以用外部日志区来解决这个问题。
- 内部日志区:日志区在同一个文件系统内部
- 外部日志区:将另外一个分区作为日志区
外部日志区最好是使用另外一块硬盘,最好是使用SSD
来做一个实验:
dumpe2fs /dev/vdb1
去掉文件系统日志区:
tune2fs -O ^has_journal /dev/vdb1
再次执行 dumpe2fs /dev/vdb1 查看没有日志区了。
创建日志区:
mke2fs -O journal_dev -b 4096 /dev/vdd1
最后,将/dev/vdd1 设置为/dev/vdb1 的外部日志区:
tune2fs -j -J device=/dev/vdd1 /dev/vdb1
验证结果:
dumpe2fs /dev/vdb1
journal size 已经没有了,取而代之的是一个journal device,这是一个十六进制的值,fc 转换成十进制数是(1516)+12=252,31转换成十进制数是(316)+1=49,这是一个主编号和次编号,对应的设备就是/dev/vdd1
UUID 也是对应的。
IBM AIX 支持多个分区共享同一个外部日志区
/dev/vdb1 /dev/vdc1 --> /dev/vdd1
必须都是ext 系列
如果是不同的文件系统,则可以从/dev/vdd 中分配
/dev/vdd1 给/dev/vdb1
/dev/vdd2 给/dev/vdc1
如果是xfs 文件系统:
如果需要写入/etc/fstab 文件,在default参数后面打逗号加参数(,logdev=/dev/sdc1)这样来写。
其实xfs 文件系统在格式化的时候,还有一些调优参数可供选择,像su参数,类似于raid 的条带大小,所谓条带大小就是系统往一组硬盘写入数据时,一次是以多大来切割原文件进行写入,那么这个su 参数就应该raid 的stripe 参数相对应,这样可以获得更好的写性能,这里就不详细展开了。
持续更新中...