上一篇文章介绍了 LVM 的基础概念和日常操作。这篇文章聚焦 LVM 在数据保护方面的三大核心机制:快照、镜像、条带化,以及它们在真实生产环境中的使用策略。
一、LVM 快照(Snapshot)
LVM 快照让你可以在几秒钟内创建一个逻辑卷的"冻结副本",用于备份或测试,对原卷几乎无性能影响。
工作原理
LVM 快照基于 COW(Copy-On-Write,写时复制) 技术:
快照创建瞬间
┌─────────────────────┐
│ 原卷(Origin LV) │ ← 原卷数据不变
│ A B C D E F G H │
└─────────────────────┘
│
┌───────┴───────┐
│ 快照卷 │ ← 几乎不占空间,只记录变化
│ (空白的) │
└───────────────┘
快照创建后,原卷数据发生变化时
┌─────────────────────┐
│ 原卷 │
│ A B C X Y F G H │ ← E→X, D→Y 被覆盖
│ ↑ ↑ │
└─────│───│───────────┘
│ │ COW:原数据被覆盖前复制到快照
┌─────┴───┴───────────┐
│ 快照卷 │
│ E D │ ← 只存了被修改前的原数据
└─────────────────────┘关键点:
- 快照创建时瞬间完成(秒级),无论原卷多大
- 快照不复制全部数据,只记录原卷被修改前的老数据
- 快照卷会随着原卷的修改量增长而占用空间
- 快照卷空间用尽后自动失效(变为不可用)
创建快照
# 创建一个 5GB 的快照卷
# -s: snapshot
# -L: 快照大小(建议为原卷的 10-20%)
lvcreate -L 5G -s -n data_snap /dev/data_vg/data_lv
# 查看快照
lvs
# LV VG Attr LSize Origin Snap%
# data_lv data_vg owi-aos--- 60.00g
# data_snap data_vg swi-a-s--- 5.00g data_lv 0.00使用快照进行备份
# 1. 创建快照
lvcreate -L 5G -s -n mysql_snap /dev/data_vg/mysql_lv
# 2. 挂载快照(只读,保证备份一致性)
mkdir -p /mnt/snap
mount -o ro /dev/data_vg/mysql_snap /mnt/snap
# 3. 从快照备份数据
rsync -av /mnt/snap/ /backup/mysql/
# 4. 卸载并删除快照
umount /mnt/snap
lvremove /dev/data_vg/mysql_snap快照空间耗尽的风险
这是生产环境最容易踩的坑:
# 监控快照使用率
lvs -o snap_percent
# 如果快照使用率接近 100%,需要立即处理:
# 方案一:扩展快照卷
lvextend -L +5G /dev/data_vg/data_snap
# 方案二:如果备份已完成,立即删除快照
lvremove /dev/data_vg/data_snap快照不是备份! 快照依赖原卷,原卷出问题快照也会失效。快照是为了一致性备份窗口,完整的备份方案仍需异地存储。
快照的恢复
# 将原卷回滚到快照时的状态
# ⚠️ 注意:会丢失快照创建之后的所有数据变更
lvconvert --merge /dev/data_vg/data_snap
# 合并后快照卷自动删除,原卷恢复到快照时的状态合并操作要求原卷处于卸载状态。无法卸载时(如根卷),会在下次重启时自动合并。
二、LVM 镜像(Mirror)
LVM 镜像将数据实时同步写入多块物理磁盘,任何一块损坏都不影响数据完整性。
工作原理
写入数据
│
┌─────┴─────┐
│ LVM 镜像层 │
└─────┬─────┘
┌─────┴─────┐
│ │ │
┌───┴───┐ ┌───┴───┐
│ PV1 │ │ PV2 │
│ /dev/ │ │ /dev/ │
│ sdb │ │ sdc │
└───────┘ └───────┘
写两份数据 完全独立创建镜像逻辑卷
# 需要至少 2 个 PV 在不同的物理磁盘上
# 创建镜像 LV(-m1 表示 1 个镜像副本,总计 2 份数据)
lvcreate -L 50G -m1 -n mirrored_lv data_vg /dev/sdb /dev/sdc
# 查看镜像状态
lvs -a -o name,attr,size,mirror_log,devices data_vg验证镜像
# 查看镜像的组成设备
dmsetup deps /dev/data_vg/mirrored_lv
# 查看 LV 详细信息
lvdisplay -m /dev/data_vg/mirrored_lv
# 输出会显示:
# --- Logical volume ---
# LV Name mirrored_lv
# LV Status available
# # open 1
# Mirror suspended 0
# **Mirror legs 2** ← 两个镜像副本
# **Mirror sync 100.00%** ← 同步进度模拟磁盘故障
# 模拟 /dev/sdc 损坏
# 查看哪些 PV 被镜像使用
lvdisplay -m /dev/data_vg/mirrored_lv
# LVM 会自动将故障 leg 标记为"无效",但仍可从另一个 leg 正常读写
# 查看状态
lvs -a -o name,attr,devices data_vg
# 显示 "m" 开头的属性表示镜像不可用
# 移除故障 leg
lvconvert --repair /dev/data_vg/mirrored_lv
# 更换新盘后加入镜像
vgextend data_vg /dev/sdd
lvconvert -m1 /dev/data_vg/mirrored_lv /dev/sddRAID1 vs LVM 镜像
| 对比项 | LVM 镜像 | 硬件 RAID1 | mdadm RAID1 |
|---|---|---|---|
| 性能 | 中等(软件层) | 最好 | 较好 |
| 热插拔 | 需手动修复 | 自动 | 自动 |
| 灵活性 | 可结合快照/条带 | 固定配置 | 较灵活 |
| 适用场景 | 不想用硬件 RAID 的服务器 | 关键生产环境 | 通用 Linux 服务器 |
三、LVM 条带化(Striping)
条带化将数据分片后并行写入多块磁盘,提升 I/O 性能。这是 RAID0 在 LVM 中的等价物。
工作原理
数据块:ABCDEFGH
│
┌────┴────┐
│ 条带 64KB│
└────┬────┘
┌────┴────┬────┴────┐
│ PV1 │ PV2 │
│ A C E G│ B D F H│
│ /dev/ │ /dev/ │
│ sdb │ sdc │
└─────────┴─────────┘
交替写入 并行读写创建条带化 LV
# -i 2:在 2 个 PV 上条带化
# -I 64:条带大小 64KB
lvcreate -L 100G -i 2 -I 64 -n striped_lv data_vg \
/dev/sdb /dev/sdc
# 格式化(建议使用支持并行 I/O 的文件系统)
mkfs.ext4 /dev/data_vg/striped_lv性能验证
# 对比单盘和条带化的写入性能
# 条带化 LV
dd if=/dev/zero of=/mnt/striped/test bs=1M count=1000 conv=fdatasync
# 单盘 LV(无条带)
dd if=/dev/zero of=/mnt/single/test bs=1M count=1000 conv=fdatasync条带化的风险
条带化没有数据冗余。 任何一块磁盘损坏,整个逻辑卷的数据都会丢失。
生产建议:
- 条带化 + 镜像结合使用(先镜像再条带,或硬件 RAID 做底层)
- 或条带化仅用于临时数据、缓存、可重建的数据
- 不要在没有 RAID 的条带化 LV 上存放唯一数据
四、条带+镜像混合(RAID10 等效)
LVM 支持同时使用条带化和镜像,实现 RAID10 级别的保护和性能。
# --type raid10:LVM 内置的 RAID10
lvcreate --type raid10 -L 100G -i 2 -m1 -n raid10_lv data_vg
# 需要至少 4 个 PV(2 组镜像 × 2 条带)
# 等同于 Linux md RAID10查看 RAID10 LV 的状态:
lvs -a -o name,attr,raid_sync_action,raid_mismatch_count,devices data_vg五、thin provisioning(精简配置)
LVM 的 thin pool 允许创建"超额分配"的逻辑卷,按需使用物理空间。
# 1. 创建 thin pool(实际的物理存储池)
lvcreate -L 100G -T data_vg/thin_pool
# 2. 在 pool 中创建 thin LV(可以超额分配)
lvcreate -V 200G -T data_vg/thin_pool -n thin_lv1
lvcreate -V 200G -T data_vg/thin_pool -n thin_lv2
# 3. 查看实际使用
lvs -o+size,data_percent
# thin_pool 显示 100G(物理)
# thin_lv1/thin_lv2 各显示 200G(虚拟),但实际只占用了写入的部分风险控制: 监控 thin pool 的实际使用率,接近 100% 时及时扩展。
# 扩展 thin pool
lvextend -L +50G /dev/data_vg/thin_pool
# 设置自动扩展阈值(通过 dmeventd)
lvchange --monitor y /dev/data_vg/thin_pool六、生产环境数据保护策略
分层保护模型
┌─────────────────────────────────────┐
│ 文件系统层(ext4/xfs) │
│ fsck / xfs_repair │
├─────────────────────────────────────┤
│ LVM 层 │
│ 镜像/快照/条带化 │
├─────────────────────────────────────┤
│ 硬件/驱动层 │
│ 硬件 RAID / NVMe 镜像 │
├─────────────────────────────────────┤
│ 备份层 │
│ 异地备份 / 对象存储 │
└─────────────────────────────────────┘不同场景的保护方案
| 场景 | 推荐方案 | 原因 |
|---|---|---|
| 数据库 | 快照备份 + 硬件 RAID1 | 一致性快照做备份,RAID 防单盘故障 |
| 文件服务器 | 镜像 LV | 实时保护,自动容错 |
| 日志集群 | 条带化 LV | 追求写性能,数据可重建 |
| KVM 虚拟机盘 | thin pool + 快照 | 超额分配节省空间,快照做增量备份 |
| 冷数据归档 | 单盘 LV + 压缩 | 不需要高性能,省成本 |
最佳实践清单
# 1. 监控卷组空闲空间(快照会消耗空间)
watch -n 60 'vgs --noheadings -o vg_free'
# 2. 监控快照使用率
watch -n 300 'lvs -o name,snap_percent'
# 3. 定期检查镜像完整性
lvdisplay -m /dev/vg/lv | grep "mirror"
# 4. 快照自动清理脚本(crontab)
# 30 2 * * * lvremove -f /dev/data_vg/old_snap 2>/dev/null
# 5. 日志集中管理 LVM 事件
grep -i "lvm\|volume group\|logical volume" /var/log/syslog七、总结
| 机制 | 解决的问题 | 代价 | 适用场景 |
|---|---|---|---|
| 快照 | 一致性备份、快速回滚 | 原卷修改时消耗快照空间 | 数据库备份、升级前快照 |
| 镜像 | 单盘故障不丢数据 | 50% 空间用于冗余 | 关键业务数据 |
| 条带化 | 提升 I/O 性能 | 无冗余,一盘坏全丢 | 高性能临时数据 |
| Thin pool | 空间超额分配 | 必须监控实际使用率 | 虚拟机、测试环境 |
| RAID10 | 性能 + 冗余 | 50% 空间 + 4 盘起步 | 生产数据库 |
核心原则:
- 快照 ≠ 备份,快照是备份的工具而非替代品
- 镜像防单盘故障,但不防火烧机房(仍需异地备份)
- 条带化是双刃剑——用得好是性能利器,用不好是数据杀手
- 生产环境至少做到:本地冗余(镜像/RAID)+ 异地备份