引言
物理磁盘是「死」的:一块 1TB 的盘分区后就固定了大小,想扩容只能停机、备份、重建、恢复。LVM(Logical Volume Manager) 把存储抽象成可自由伸缩的「逻辑卷」,支持在线扩容、快照、跨盘聚合;RAID 则解决「单盘故障不丢数据」与「多盘聚合性能」。两者叠加是 Linux 服务器存储的常见底座:RAID 保硬件冗余、LVM 保灵活伸缩,上层的文件系统与数据库只是消费者。
本文先讲透 LVM 的三层抽象与完整操作(建、扩、缩、快照、thin、cache),再深入 mdadm 软 RAID 的级别选择、chunk 大小、坏盘替换与扩容,最后给出一套故障恢复与排错流程。目标是让你能在不停机的前提下完成绝大多数存储变更。
前置:磁盘、分区与文件系统基础见 Linux 文件系统与磁盘管理 ,本文是其存储进阶篇;RAID 对性能的影响见 Linux IO 栈与存储性能调优 ,快照备份见 Linux 备份与容灾 。
1. LVM 三层抽象:PV、VG、LV
LVM 把存储分成三层,理解这三层就理解了全部:
物理卷 PV ← 一块磁盘或一个分区(/dev/sdb、/dev/sdb1)
↓ 归入
卷组 VG ← 一个「存储池」,由若干 PV 组成(vg0)
↓ 切出
逻辑卷 LV ← 从池里切出的「虚拟分区」(/dev/vg0/data),可格式化、挂载
/dev/sdb ─┐
├─→ VG: vg0 ─→ LV: lv_data (100G) ─→ mkfs.xfs ─→ /data
/dev/sdc ─┘ └─→ LV: lv_log (20G) ─→ mkfs.ext4 ─→ /log
| 层级 | 命令前缀 | 作用 |
|---|---|---|
| PV | pv* | 把设备「标记」为 LVM 可用的物理卷 |
| VG | vg* | 把多个 PV 聚合成池,决定总容量 |
| LV | lv* | 从池里切卷,是最终可格式化的设备 |
心智:PV 是「砖」、VG 是「砖砌的池子」、LV 是「从池里舀出的一桶水」。扩容的本质就是「往池子里加砖」或「把桶换大」。
2. 从零建一套 LVM
# 1. 创建物理卷
sudo pvcreate /dev/sdb /dev/sdc
sudo pvs # 查看 PV 概览
# 2. 创建卷组(把两块盘合成一个池)
sudo vgcreate vg0 /dev/sdb /dev/sdc
sudo vgs # 查看 VG 容量与剩余
# 3. 从池里切逻辑卷
sudo lvcreate -L 100G -n data vg0 # 固定大小 100G
sudo lvcreate -l 100%FREE -n log vg0 # 剩余全部给 log
# 4. 格式化并挂载
sudo mkfs.xfs /dev/vg0/data
sudo mkdir -p /data && sudo mount /dev/vg0/data /data
# 5. 写入 fstab 持久化
echo "/dev/vg0/data /data xfs defaults,noatime 0 0" | sudo tee -a /etc/fstab
# 查看全景
pvs ; vgs ; lvs
lsblk # 块设备树(能看出 LVM 层级)
lvdisplay /dev/vg0/data # 单卷详情
| 选项 | 含义 |
|---|---|
-L 100G | 指定绝对大小 |
-l 100%FREE | 用剩余空间的百分比 |
-l 50%VG | 用卷组总容量的百分比 |
-n name | 逻辑卷名 |
-s | 创建快照 |
铁律:
pvcreate会抹掉设备上原有的分区表和文件系统。对已有数据的盘操作前,务必确认它没有要保留的内容。
3. 在线扩容与缩容
LVM 最大的价值是在线扩容——加盘、扩卷、扩文件系统,全程不停机。
# 场景一:VG 还有空闲空间,直接扩 LV
sudo lvextend -L +50G /dev/vg0/data # 加 50G
sudo xfs_growfs /data # XFS 在线扩容
# 或 ext4:sudo resize2fs /dev/vg0/data
# 场景二:VG 空间不够,先加一块盘进池
sudo pvcreate /dev/sdd
sudo vgextend vg0 /dev/sdd # 池子变大
sudo lvextend -l +100%FREE /dev/vg0/data
sudo xfs_growfs /data
# 一条命令搞定「扩卷 + 扩文件系统」
sudo lvextend -r -L +50G /dev/vg0/data # -r 自动 resize 文件系统
缩容比扩容危险得多,且 XFS 不支持缩容:
# ext4 缩容三步(顺序不能错,先缩文件系统再缩卷)
sudo umount /data
sudo e2fsck -f /dev/vg0/data # 必须检查
sudo resize2fs /dev/vg0/data 50G # 先缩 FS
sudo lvreduce -L 50G /dev/vg0/data # 再缩 LV
sudo mount /dev/vg0/data /data
| 文件系统 | 扩容 | 缩容 |
|---|---|---|
| XFS | 在线 xfs_growfs | 不支持 |
| ext4 | 在线 resize2fs | 支持,需 umount |
| Btrfs | 在线 | 支持 |
铁律:XFS 不能缩容,ext4 缩容必须先缩文件系统再缩 LV。顺序颠倒会直接损坏文件系统;不确定时宁可新建卷迁移数据。
4. 快照:经典快照与 thin 快照
LVM 快照是 COW(copy-on-write):创建瞬间几乎不占空间,之后原卷被修改的块才复制到快照空间。
# 经典快照:需预留足够空间存放「变化量」
sudo lvcreate -L 10G -s -n data_snap /dev/vg0/data
sudo mount /dev/vg0/data_snap /mnt/snap # 只读或读写挂载
经典快照的关键限制:快照空间用完(COW 溢出)后快照会失效(标记 Invalid)
→ 快照大小必须 ≥ 「快照存活期间原卷的变化量」
→ 长期保留的快照要么开 thin,要么定期删除
| 快照类型 | 空间分配 | 适用 |
|---|---|---|
| 经典快照 | 预分配固定大小 | 短时备份、验证、临时回滚 |
| thin 快照 | 按需分配 | 长期保留、多版本、大量快照 |
# 从快照恢复:把快照内容拷回原卷
sudo lvconvert --merge /dev/vg0/data_snap # 合并(需卸载原卷)
# 或挂载快照把数据 rsync 回去
心法:经典快照适合「备份窗口内的一致性视图」,不适合长期保留。要做「保留多个历史版本」的用法,请用 thin 快照。
5. Thin Provisioning 与精简池
Thin provisioning(精简置备)让 LV 的「声明大小」可以大于池的实际容量——空间按需分配,直到真正写入才占用。
# 1. 建 thin pool(池大小 200G,元数据 1G)
sudo lvcreate -L 200G --thinpool tp0 vg0
# 2. 在池里建 thin 卷,声明 500G(可超池容量)
sudo lvcreate -V 500G --thin -n thin_data vg0/tp0
sudo mkfs.xfs /dev/vg0/thin_data
# 监控 thin pool 使用率——这是必须持续关注的指标
lvs -o name,size,data_percent,metadata_percent vg0
# 或
sudo lvs vg0/tp0 -o lv_name,data_percent,metadata_percent
| 术语 | 含义 |
|---|---|
| thin pool | 实际承载空间的池(tp0) |
| thin volume | 池里声明大小的虚拟卷 |
| data_percent | 池数据占用率(逼近 100% 会出问题) |
| metadata_percent | 元数据占用率 |
# 设置自动扩容阈值(在 /etc/lvm/lvm.conf 里可配 thin_pool_autoextend_threshold)
# 更常见的做法是配监控告警:data_percent > 80% 就扩容或清理
铁律:thin pool 用满(data_percent=100%)会导致所有 thin 卷写入失败,比普通盘满更严重。必须配监控;
lvextend扩容 thin pool 时用--poolmetadatasize一并确认元数据足够。
6. LVM Cache 与 SSD 加速
lvmcache 用一块快速设备(SSD/NVMe)做慢速大容量盘(HDD)的写回/写穿缓存,提升热数据访问速度。
# 准备 fast(SSD)与 slow(HDD)两个 LV 或设备
sudo lvcreate -L 100G -n cache_lv vg0 /dev/nvme0n1 # 缓存盘
sudo lvcreate -L 2T -n data_lv vg0 /dev/sdb # 主数据
# 创建缓存池并挂到主卷
sudo lvconvert --type cache-pool --cachemode writethrough \
--poolmetadata vg0/cache_lv vg0/data_lv # 简化示例,实际参数按版本
| 缓存模式 | 行为 | 风险 |
|---|---|---|
writethrough | 写同时落缓存与后端 | 安全,写性能提升有限 |
writeback | 写先落缓存,异步刷后端 | 快,但缓存盘故障可能丢数据 |
# 查看缓存命中情况
lvs -o name,cache_mode,cache_total_blocks,cache_read_hits,cache_write_hits vg0
dmsetup status vg0-data_lv
心法:writeback 缓存性能好但把「缓存盘可靠性」提到了关键路径上。缓存盘最好是企业级、带掉电保护(PLP)的 SSD,且不要与数据盘共用同一物理故障域。
7. mdadm 软 RAID:级别、chunk 与创建
mdadm 是 Linux 软件 RAID 的标准工具。RAID 级别决定「冗余方式」,chunk 决定「条带粒度」。
# 创建 RAID1(两块盘镜像)——系统盘/日志盘常用
sudo mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sdb /dev/sdc
# 创建 RAID10(镜像+条带)——数据库首选
sudo mdadm --create /dev/md1 --level=10 --raid-devices=4 \
--layout=f2 /dev/sd[b-e]
# 创建 RAID5(单盘校验,至少 3 盘)
sudo mdadm --create /dev/md2 --level=5 --raid-devices=3 /dev/sd[bcd]
# 查看阵列
cat /proc/mdstat
sudo mdadm --detail /dev/md0
| 级别 | 最少盘 | 冗余 | 容量利用率 | 适用 |
|---|---|---|---|---|
| RAID0 | 2 | 无 | 100% | 临时数据、可重建 |
| RAID1 | 2 | 1 盘 | 50% | 系统盘、日志 |
| RAID5 | 3 | 1 盘 | (n-1)/n | 读多写少、大容量 |
| RAID6 | 4 | 2 盘 | (n-2)/n | 大容量高可靠 |
| RAID10 | 4 | 每镜像 1 盘 | 50% | 数据库、高 IOPS |
chunk 大小(--chunk=,默认 512K)决定条带粒度:大 chunk 适合顺序大 IO,小 chunk(64K~256K)适合随机 IO 的并行度。
# 查看 chunk
sudo mdadm --detail /dev/md0 | grep -i chunk
# 创建时指定(随机数据库负载常用 64K~128K)
sudo mdadm --create /dev/md1 --level=10 --chunk=128 --raid-devices=4 /dev/sd[b-e]
记忆:RAID 级别看「冗余」,chunk 看「性能粒度」。数据库随机 IO 选 RAID10 + 小 chunk;大文件顺序存储 RAID5/6 + 大 chunk 更划算。
8. RAID 运维:坏盘替换、扩容与 scrub
# 1. 发现坏盘(阵列降级)
cat /proc/mdstat # 显示 [U_] 表示有盘掉了
sudo mdadm --detail /dev/md0 | grep -i state
dmesg | grep -i -E 'md|ata|I/O error'
# 2. 标记故障盘并移除
sudo mdadm --manage /dev/md0 --fail /dev/sdc1
sudo mdadm --manage /dev/md0 --remove /dev/sdc1
# 3. 插入新盘并加入阵列(自动开始 rebuild)
sudo mdadm --manage /dev/md0 --add /dev/sdc1
cat /proc/mdstat # 看 resync/rebuild 进度
# 4. 保存阵列配置,保证开机自动组装
sudo mdadm --detail --scan | sudo tee -a /etc/mdadm/mdadm.conf
sudo update-initramfs -u
| 操作 | 命令 |
|---|---|
| 查阵列状态 | cat /proc/mdstat |
| 标记故障 | mdadm --manage /dev/mdX --fail /dev/sdY |
| 移除盘 | mdadm --manage /dev/mdX --remove /dev/sdY |
| 加入新盘 | mdadm --manage /dev/mdX --add /dev/sdY |
| 扩容成员 | mdadm --grow /dev/mdX --raid-devices=N |
| 一致性校验 | echo check > /sys/block/mdX/md/sync_action |
| 查校验进度 | cat /sys/block/mdX/md/sync_completed |
# 定期 scrub 校验(发现静默数据损坏),每月一次
echo check | sudo tee /sys/block/md0/md/sync_action
# 限速避免影响业务(单位 KB/s,0 表示不限)
echo 50000 | sudo tee /sys/block/md0/md/sync_speed_max
心法:rebuild 期间阵列是「脆弱」的(RAID5 降级时再坏一块就全丢)。替换坏盘要尽快,且 rebuild 会吃 IO,业务高峰避开、必要时限速。
9. 故障恢复与排错
# LVM 元数据损坏的排查
sudo pvck /dev/sdb # 检查 PV 元数据完整性
sudo vgcfgbackup vg0 # 备份 VG 配置到 /etc/lvm/backup
sudo vgcfgrestore vg0 # 从备份恢复
ls /etc/lvm/archive/ # 历史配置归档
# 阵列不自动组装
sudo mdadm --assemble --scan
sudo mdadm --examine /dev/sdb1 # 检查成员盘超级块
# 文件系统层面
sudo xfs_repair -n /dev/vg0/data # 只检查不修改
sudo e2fsck -f /dev/vg0/data # ext4 修复
| 现象 | 可能原因 | 对策 |
|---|---|---|
| VG 不激活 | 缺 PV 或元数据损坏 | vgchange -ay / vgcfgrestore |
| 阵列降级 | 单盘故障 | 换盘 + --add 触发 rebuild |
| 阵列不自动起 | 缺 mdadm.conf | --detail --scan 写入配置 |
| 卷莫名变小 | 快照 COW 溢出 | 删除失效快照、重建 |
| thin 卷只读 | thin pool 满 | 扩容 thin pool |
# 恢复前务必先备份元数据
sudo vgcfgbackup vg0
sudo mdadm --detail --scan > /root/md.conf.bak
铁律:任何 LVM/RAID 操作前先
vgcfgbackup与保存mdadm --detail --scan。元数据比数据更容易被误操作毁掉,有了备份几乎任何布局都能重建。
10. 速查表
| 需求 | 命令 |
|---|---|
| 建 PV/VG/LV | pvcreate → vgcreate → lvcreate |
| 查看 | pvs / vgs / lvs / lsblk |
| 扩容卷组 | vgextend vg0 /dev/sdd |
| 扩容逻辑卷 | lvextend -r -L +50G /dev/vg0/data |
| 缩容(ext4) | umount → resize2fs → lvreduce |
| 经典快照 | lvcreate -L 10G -s -n snap /dev/vg0/data |
| 建 thin pool | lvcreate -L 200G --thinpool tp0 vg0 |
| 建 thin 卷 | lvcreate -V 500G --thin -n v vg0/tp0 |
| 建 RAID1 | mdadm --create /dev/md0 -l 1 -n 2 /dev/sd[bc] |
| 换坏盘 | --fail → --remove → --add |
| 校验阵列 | echo check > /sys/block/md0/md/sync_action |
| 备份元数据 | vgcfgbackup + mdadm --detail --scan |
一句话记忆:RAID 保冗余、LVM 保灵活——PV 归入 VG、VG 切出 LV,在线扩容用 lvextend -r,快照靠 COW(经典需预留、thin 按需),thin pool 用满会全局只读;mdadm 用 --level 定冗余、--chunk 定粒度,坏盘 --fail/--remove/--add 三步换新。
延伸阅读
- Linux 文件系统与磁盘管理 — 分区、挂载与 fstab 基础
- Linux IO 栈与存储性能调优 — RAID 布局对 IOPS/延迟的影响
- Linux 高级文件系统 — XFS/Btrfs/ZFS 的选型与特性
- Linux 备份与容灾 — 快照与 3-2-1 备份策略
- Linux 磁盘加密与 LUKS — LVM 之上的加密层
- 数据库专题 — 存储布局对数据库性能的影响
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。