Linux系统中的存储方案层出不穷,让人眼花缭乱。在安装的时候,分区界面的选项也有很多。如果用安装光盘一键自动划分分区,系统盘占满了,还怎么修?理解Linux的存储模型是合理分区、运用各种存储方案的关键。
计算机存储系统实际上可以认为只有两层,底层是块设备,一块连续的存储空间,如一块硬盘或一个分区;上层是文件系统,管理经典的目录树结构。

1. 块设备层:化整为零,化零为整

存储系统的最底层是物理硬盘,但操作系统并不直接与闪存颗粒或磁道扇区打交道,而是通过ATA和SCSI协议来访问硬盘,再给出“块设备”这个抽象接口。

块设备将存储介质抽象为一个可以按固定大小块(如512字节、4K)随机读写的线性空间。我们常见的/dev/sda/dev/nvme0n1就是硬盘本身的块设备文件。然而,直接使用整块硬盘非常不灵活,根据不同的用途,需要将硬盘先切为几块再用。

分区表定义了如何将一块物理硬盘划分为多个独立的分区(又称为卷 Volume,如/dev/sda1),从而实现了在同一块硬件上隔离不同用途的数据,比如分开操作系统和用户文件。MBR是DOS时代遗留下来的分区表格式,只支持4个主分区、最大2TB,现在一般用GPT分区表格式替代了。

分区依然受限于单块物理硬盘的边界,且不易扩展和调整。如果硬盘空间耗尽,扩展分区往往需要停机、备份数据,耗时耗力地重新划分分区。

逻辑卷管理器(LVM) 的引入突破了这一限制。LVM对硬盘做了二次抽象:先将普通分区格式化为“物理卷(PV)”,然后聚合成“卷组(VG)”,最后从卷组中按需切分出灵活的“逻辑卷(LV)”。物理卷(PV)就类似分区表,卷组(VG)类似新组建了一块大硬盘,在其上划分了多个分区,就是逻辑卷(LV),逻辑卷呈现为一个块设备。逻辑卷可以动态扩容、缩小,甚至跨越多块物理硬盘,极大地提升了存储管理的灵活性。

为提高性能、解决容量限制,将多块硬盘拼成一块,就必须考虑单块硬盘寿命的影响。独立磁盘冗余阵列(RAID) 通过将数据以特定方式分布到多块硬盘上,实现了数据冗余(如RAID 1/5/6)或性能提升(如RAID 0)。在Linux上,可以在不同层面实现:可以通过专用的物理阵列卡或磁盘阵列服务器接入,直接显示为一整块“物理硬盘”;也可以通过mdadm工具创建RAID块设备,作为一块逻辑硬盘;还可以用LVM,创建RAID类型的逻辑卷LV,作为一个分区。

为了将存储设备和计算设备分离,iSCSI网络块设备(NBD) 可以通过网络,拉一根数据线,将远程的储存空间作为本地硬盘来使用。iSCSI是一个功能完备、兼容广泛的标准协议,很多NAS和磁盘阵列服务器都支持将虚拟卷映射到iSCSI端口。NBD是Linux上原生的块设备共享协议,安装和配置相对简单。

Linux 内核通过 /dev 下统一的设备文件给出这些块设备的接口,并自动处理分区表,将分区表中包含的分区也作为独立的块设备。例如 /dev/sda 是一整块硬盘,/dev/sda1 是这块硬盘的第一个分区。实际操作中,可以用 /dev/disk/by-id 或 /dev/disk/by-uuid 下的链接指代硬盘或分区,能防止插拔后编号变动带来不便。这个统一的块设备层,是上层文件系统无需关心硬件实现的前提。

2. 文件系统层:功能、性能、稳定性的权衡

文件系统是非常复杂的组件。在熟悉的目录树结构下,文件系统不仅要高性能地实现读写,还要管理各种文件属性,实现并发控制,用日志保证完整性等。Linux 下的文件系统,每种都在根据它的适应场景迭代升级。

ext4 是 Linux 上最广泛使用的文件系统,稳定、高效、易用。XFS 与 ext4 在功能和性能上比肩,能支持更大的文件和高并发 IO。考虑到 ext4 支持缩小,第三方支持(数据恢复工具)更完善,一般情况下还是建议直接使用默认的 ext4。

Btrfs 的写时复制(COW)和快照功能在数据备份场景下非常友好,包括很多高级特性,如数据压缩、完整性检查、子卷、去重等,原先被认为是 ext4 的继任者。然而这个文件系统长年被“不稳定”的阴影笼罩,且性能明显落后于其他文件系统,所以目前基本上只在数据备份、扩展存储(NAS)领域得到广泛应用。Btrfs 也计划支持多盘阵列,但相关功能还有很多严重问题未修复。

与 Btrfs 并列的 ZFS 支持类似的功能,其稳定性得到了广泛的验证,且支持文件系统级别的多磁盘管理,实现类似 RAID 的数据冗余机制。其问题在于许可证限制不能包含在 Linux 内核内,升级维护成本较高。

除了管理本地块设备,文件系统的概念还可以通过网络延伸。NFSSMB/CIFS 是两种主流的网络文件系统协议,它们允许客户端像访问本地目录一样访问远程服务器共享的文件。这种抽象简化了文件共享,但引入了更多不确定因素,如难以确保各客户端的一致性;当网络不稳定时,极易引发读写文件时进程挂起。

为了在用户空间灵活实现各种文件系统,Linux 提供了 FUSE 框架,它使得开发者无需修改内核就能创建新的文件系统。例如 sshfs,可以直接用 ssh 协议挂载远程主机上的文件夹。在FUSE框架下,可以用各种语言无限制地实现功能,显然性能、稳定性就得不到保证了。

各种文件系统的共同点是提供给上层统一的目录树接口,区别就在于如何有效利用底层块存储或网络,实现各自的特色功能。

3. 具体场景下的选型

面对千变万化的存储需求,Linux 强大的存储分层模型提供了灵活的组合方案,其核心在于理解每一层抽象解决的问题,并基于具体场景匹配最合适的层级和技术。

对于配置固定、用途明确且无需后续扩展的单机系统(如嵌入式设备、特定用途服务器),可以直接使用分区表分区。如将硬盘直接分为系统根目录和 Swap 交换分区(即虚拟内存),系统分区格式化为 ext4。

云上虚拟机,或高配置台式机的存储需求可能会经常增长。这时,可以用 LVM 管理分区。当单个 LV 空间不足时,管理员可以在线增减分区,或在线扩展其所属 VG 的容量(添加新云盘或扩展现有云盘),然后无缝扩展 LV 及其上的文件系统。整个过程通常无需停机,也避免了传统分区方案中需要备份数据、移动分区的繁琐和风险。

使用LVM的典型Linux分区方案
(图:使用LVM的典型Linux分区方案)

用固态硬盘加速大容量机械硬盘是一个常见需求。稳定可靠的做法是通过 LVM 的缓存机制,将固态硬盘和机械硬盘放入同一个 VG 卷组,在机械硬盘上先创建主数据分区,再在固态硬盘上附加缓存分区。

lvcreate --type cache --cachemode writeback -L <大小> -n <名称> <vg/pv> </dev/SSD的PV分区>

同时使用多块硬盘扩展容量时,必须考虑可用性的保证。由于现代硬盘容量非常大,恢复时的大量读写容易导致相似寿命的第二块硬盘提前损坏,大于三块硬盘时应避免使用 RAID5,可以直接在 RAID10(性能)和 RAID6(安全性)中选择。Linux 上有多种实现途径:一种是用 mdadm 直接管理软件阵列,将硬盘组合为一块逻辑硬盘;一种是用 LVM 创建 raid 类型的 LV 逻辑分区;一种是用 ZFS 管理多块硬盘,创建 raidz2 模式的 zpool 存储池。

三种RAID6的实现方式
(图:三种RAID6的实现方式)

需要注意的是,在上述硬盘阵列的实现过程中,实际上既可以直接在硬盘块设备上操作,也可以在分区块设备上操作。为了防止第三方软件和系统误认为硬盘上没有数据,应先创建GPT分区表,在分区上创建RAID阵列、PV物理卷或ZFS文件系统。

在网络存储中,应优先选择块设备(iSCSI/NBD)的方式共享存储,性能损耗小。其次,接口简洁的对象存储接口(如S3)也要比NFS/SMB更适用于现代应用,减少了网络波动、锁机制问题的影响范围。

处理海量小文件(如小图片、JSON/XML)的场景已经不适合使用文件系统。这类场景下,文件系统元数据操作是很大的瓶颈。此时,可以直接将数据存储在数据库中(如 SQLite, PostgreSQL),便于查找和事务管理,也减少了读写开销。

数据库(如PostgreSQL)的存储机制与Linux存储系统的分层模型也可以类比。数据库的表数据最终以物理文件形式存储在磁盘上,这些文件就如同块设备,用分页结构管理线性存储空间;而表的逻辑结构(字段定义)则类似文件系统的目录树,为用户提供了结构化的访问接口。用户通过SQL语句操作表时无需关心底层文件的存储细节,正如操作目录树时,文件系统屏蔽了块设备的物理地址和访问模式。

这种分层设计的核心价值在于显著提升了存储系统的可扩展性与灵活性,每一层都专注解决特定问题。块设备层通过分区、RAID等技术实现存储资源的隔离与聚合,文件系统层则通过不同的格式满足性能、功能或稳定性需求,各层独立迭代又可灵活组合,让存储方案能适配从嵌入式设备到分布式集群的各种场景。

提高存储性能本质上是减少不必要的读写开销:例如ext4的数据结构比Btrfs更简单,所以元数据操作性能更优;iSCSI/NBD作为块设备共享时,相比NFS/SMB等网络文件系统,减少了协议层的复杂交互,上层文件系统合并了区块的读写,从而降低了读写延迟。

可维护性则依赖于对成熟技术的选择,选择成熟、稳定且运维团队熟悉的技术栈,能大幅降低故障排查与日常运维的复杂度,让存储系统在灵活扩展的同时保持可靠与可控。

因此在实践中,理解分层模型、明晰每层技术解决的问题及其接口,并基于具体场景做出平衡和务实的选择,是构建可靠、高效存储系统的关键。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐