文章概览
Linux文件系统
首先我们要知道:linux系统中一切皆文件
进入linux系统就可以看到下面目录结构,应该很熟悉
可以再深入了解一下
安装系统的时候会指定安装硬盘,然后创建分区,当硬盘分区创建好之后会选择合适的文件系统(一般默认ext4)格式化分区,mount到指定目录下就可以读写文件
来看看
ls /dev/sd* (系统中有1块硬盘并且创建了2个主分区sda1、sda2)
sudo fdisk -l /dev/sda (/dev/sda2为该系统下的文件系统)
File System In Linux
虚拟文件系统是linux内核的五大组件之一
可以看到它从 用户 -->内核 -->硬件 的整个流程
Application:上层应用
System calls:通过系统调用操作文件
File system:对文件系统的抽象
File system types:不同的文件系统(ext4,xfs…)
Block devices:不同硬盘I/O接口的抽象
Hard disk:底层硬件资源
我们已经了解到文件系统在linux内部大致的层级结构以及用户读写数据的调用流程,ext4为linux比较常用的文件系统,接下来将深入ext4
EXT发展史
- MINIX : 微机的一个非常小的Unix操作系统,最多能处理14个字符的文件名,只能处理 64MB 的存储空间
- EXT1: 第一个利用虚拟文件系统, 2GB存储空间并处理255个字符的文件
- EXT2: 商业级文件系统, GB级别的最大文件大小和TB级别的文件系统大小
- EXT3 : 增加日志功能
- EXT4:提供更佳的性能和可靠性,更大的文件系统和更大的文件、无限数量的子目录、Extents、多块分配、延迟分配,快速 fsck、日志校验,No Journaling模式
EXT4内部
ext4文件系统结构,上半部分为磁盘分区创建ext4文件系统,下半部分为ext4内部结构
EXT4内部结构
- Block:ext4文件系统中记录最小的的单位为 block(4K),每个block里面可以放8个sector(512B)
-
Block Group:将block分组合成一个个的group(128M)
计算公式:Group_size = (blk_size8)blk_size=409684096= 327684096=128M*
ext4分为很多个block group,接下来我们了解block group下的存储结构
场景:带入一个场景会更好理解,拿图书馆来类比,图书馆相当于ext4文件系统,ext4存储文件,图书馆收藏书籍,block group相当于图书馆的书架,block相当于书架上的小方格,放置一定数量的书籍,每个小方格都有唯一标识的标签(inode)
我们现在来到图书馆,想要找《redis深度历险》这本书,但是图书馆有很多不同种类的书籍,我不知道从哪找起
此时图书馆管理员给你一份手册(Superblock),记录了图书馆的一个大致信息,这个图书馆有多少个书架,每个书架上有多少个小方格已经被使用了等等,可以获取整体的一个信息
接下来我们来到一个书架边上,书架上贴着一个指引文件(Group Description),告诉我这个书架小方格的分布表(block bitmap) ,标签分布表(inode bitmap),以及它们的使用情况等等
再次上图,敲重点(hahaha…)
- Superblock: 概览,记录blocks_count, block_per_group, inodes_count, first_data_block等总的信息
- Group Description: group的基本信息,记录inode bitmap、block bitmap、inode table、free block count等等
- Block Bitmap:block分布表,记录block的使用情况(相当于书架上有个表格记录图书馆书架上每个小方格的使用情况)
- Inode Bitmap:inode分布表,记录inode的使用情况(可以理解书架的每个小方格都有自己的标签号,有个表格记录它们的使用信息)
- Inode Table:inode索引关联表,记录block的一个索引号和这个索引号对应block的一个存放位置 (类比对图书馆书架小方格的所在的位置,根据它的标签做了一个索引表方便快速查找)
注:以上都是元数据(metadata),在Data Blocks里面才存储我们真正读写的数据
那么我们到底怎么寻找到想要的书籍呢???
查找过程
我们要找的一个思路应该是:图书馆所有书籍–>计算机类–>数据库类–>《redis深度历险》
你应该首先会联想到上面的 Inode Table ,通过inode table上的索引可以找到文件所在的位置
首先获取到图书馆的inode号 1,根据inode号 1 来到图书馆看到很多类目的书架,有文学类、科技类等,于是我通过Hash算法很快的从这么类目中找到计算机类,同时获取到它的inode号 26,根据inode号 26来到计算机类的书架边上,通过hash算法找到里面的数据库类,最后找到我想要的书籍
ext4也是同样的查找过程,比如我们查找 /pg_cluster/README.md ,获取到 / 目录的inode依次向下查找就可以
注:ext4的查找算法,相对ext3的块映射的方法,优化之后使用的是extent的管理方式,有兴趣可以去了解
写过程
从上面我们已经知道数据存储在文件系统其实由两部分组成:一个是metadata(元数据),一个是filedata(真实数据)
假设我们先写元数据,再写数据块,那么过程会是:
- 从block bitmap中分配一个block,在inode中添加指向block的指针
- 把用户数据写入block
不论上面的顺序怎么调换只要不是原子性,在任意时候发生的异常都可能会导致数据异常
日志功能
日志功能可以很好的解决上面的问题
日志写入模式
-
journal :将metadata和data全部记录到日志;先写日志确保日志写入成功再写用户数据
fsync(data journal) -> fsync(metadata journal) -> fsync(data) -> fsync(metadata)
优缺点:当写入数据很大时,性能低,安全性最高
-
ordered :只将metadata写入到日志;先写用户数据(data),之后再写日志,最后写用户数据(metadata)
fsync(data) -> fsync(metadata journal) -> fsync(metadata)
优缺点:当写入数据很大时,性能低,安全性最高
-
writeback :只将metadata写入到日志,先写日志确保日志写入成功之后再写用户数据,但不保证metadata和data的写入顺序
fsync(metadata journal) -> fsync(metadata) / fsync(data)
优缺点:性能最好,安全性最低
Jouring File Systerm带来的问题
ext4默认写入模式是ordered,日志功能可以保证数据的完整性,但是也会带来一些问题
日志功能对应在linux系统上有个jdb2的进程,当持续写入数据时,会导致jdb2进程占用大量的磁盘I/O
解决办法:
- 可以找到jdb2的进程关闭日志功能(不建议)
-
对可优化的此参数进行优化
journaling modles:journal/ ordered/ writeback
barrier:0/1 (etx4默认1) [磁盘缓存]
commit:60 (etx4默认5) [Page Cache 脏页刷盘]
noatime :(etx4默认atime)
delalloc: 延迟分配
journal_dev :(ext4 默认在自己所在的分区内维护日志)
欢迎关注公众号,一起学习交流