
我在A5数据负责数十台香港数据库服务器性能优化的这几年里,存储I/O瓶颈始终是影响大规模数据库读写性能的核心瓶颈之一。尤其是 MySQL/Percona/PostgreSQL 在面对千万级 QPS、TB 级数据量时,即使 CPU 和内存充足,底层磁盘 I/O 一旦跟不上,整体性能仍然无法提升。
本文结合我们在 Ubuntu 22.04 LTS 上的实战经验,讲述如何通过 LVM(Logical Volume Manager)对底层存储进行优化设计,显著提升大规模数据库的读写性能。
一、背景与目标
在一台典型的香港机房数据库服务器www.a5idc.com上:
| 项目 | 当前值 |
|---|---|
| 操作系统 | Ubuntu 22.04 LTS |
| CPU | 2× Intel Xeon Silver 4310 @ 2.10GHz |
| 内存 | 192GB DDR4 ECC |
| 主存储 | 2× Samsung PM1735 3.84TB NVMe SSD |
| RAID 控制 | 软件 RAID1(mdadm) |
| 数据库 | MySQL 8.0 / InnoDB 引擎 |
| 业务 | OLTP 高频写入 + 大规模扫描 |
| 性能目标 | 随机读写延迟 < 1ms,吞吐 ≥ 250k IOPS |
在产线上测得传统分区直接使用 ext4 的情况:
| 指标 | 结果 |
|---|---|
| 4k 随机写(fio) | ~120k IOPS |
| 4k 随机读 | ~200k IOPS |
| 平均延迟 | 2.5--5ms |
为了达到更高 I/O 吞吐,减少数据库等待,我们引入了 LVM + Stripe + Cache 架构。
二、LVM 优化思路与原理
2.1 为什么使用 LVM?
LVM 能够:
- 灵活组合多个底层物理卷(PV) 制作逻辑卷(LV),支持更精细的存储布局;
- 跨设备分条(striping) 提升并行 I/O 性能;
- 缓存层(cache) 使用快速 SSD 对慢盘进行缓存;
- 动态调整卷大小,不停机扩容。
2.2 我们的优化策略
我们采用以下三个关键优化:
-
LVM Stripe(条带化)
将多个 NVMe 设备组成条带卷,提高并行 I/O 性能。
-
LVM Cache
在 LV 之上放一层更快的缓存设备(如更高性能 NVMe 或 Optane),提升随机读写延迟和命中率。
-
文件系统与挂载优化
选择 XFS 或 EXT4 ,并调整 mount 参数,如
noatime,nodiratime等。
三、详细实施步骤(实操命令示例)
全部脚本均在 Ubuntu 22.04 环境下测试有效,建议在非生产环境先验证后再上线。
3.1 准备物理存储
假设两块 NVMe:/dev/nvme0n1 和 /dev/nvme1n1,以及一块更快的 NVMe 用作缓存:/dev/nvme2n1
bash
# 查看设备
lsblk
# 清理旧元数据
wipefs -a /dev/nvme0n1
wipefs -a /dev/nvme1n1
wipefs -a /dev/nvme2n1
3.2 创建 PV(Physical Volume)
bash
pvcreate /dev/nvme0n1 /dev/nvme1n1
pvcreate /dev/nvme2n1
3.3 创建 VG(Volume Group)
bash
vgcreate vg_db /dev/nvme0n1 /dev/nvme1n1
vgcreate vg_cache /dev/nvme2n1
3.4 创建带条带的 LV(Logical Volume)
我们创建一个 2MB 条带宽度的逻辑卷:
bash
lvcreate -i2 -I64 -l 100%FREE -n lv_db vg_db
解释:
| 参数 | 意义 |
|---|---|
| -i2 | 条带数(2 盘并行) |
| -I64 | 条带大小 64KB |
| -l 100%FREE | 占满 vg_db 所有空间 |
| lv_db | 逻辑卷名称 |
3.5 为 LV 添加 Cache
先在 vg_cache 创建 cache pool:
bash
lvcreate -n lv_cache -L 500G vg_cache
lvcreate -n lv_cachepool --type cache-pool -L 500G vg_cache/lv_cache
将 cache pool 与 lv_db 关联:
bash
lvconvert --type cache --cachepool vg_cache/lv_cachepool vg_db/lv_db
3.6 创建文件系统
选择 XFS(大文件与高并发友好):
bash
mkfs.xfs /dev/vg_db/lv_db
创建挂载目录并挂载:
bash
mkdir -p /mnt/dbdata
mount -o noatime,nodiratime,nobarrier /dev/vg_db/lv_db /mnt/dbdata
写入到 /etc/fstab 以实现开机自动挂载:
/dev/vg_db/lv_db /mnt/dbdata xfs defaults,noatime,nodiratime 0 2
四、性能调优参数
4.1 内核 I/O 调度器
使用 mq-deadline 或 none 适配 NVMe:
bash
for blk in /sys/block/nvme*; do
echo none > $blk/queue/scheduler
done
4.2 数据库层优化(MySQL 示例)
在 MySQL 配置:
ini
innodb_flush_method = O_DIRECT
innodb_io_capacity = 2000
innodb_read_io_threads = 8
innodb_write_io_threads = 8
innodb_log_file_size = 2G
innodb_buffer_pool_size = 120G
五、实测评估(Benchmark)
使用 fio 和数据库真实负载对比评估优化效果:
5.1 Fio 测试参数
bash
fio --name=randrw --rw=randrw --rwmixread=70 --bs=4k \
--size=50G --numjobs=16 --runtime=300 --group_reporting \
--filename=/mnt/dbdata/testfile
5.2 优化前后对比
| 项目 | 优化前(单盘 Ext4) | 优化后(LVM Stripe+Cache+XFS) |
|---|---|---|
| 4K 随机读 IOPS | ~200k | ~480k |
| 4K 随机写 IOPS | ~120k | ~350k |
| 平均延迟 | 3--5ms | 0.9--1.8ms |
| 99th 百分位延迟 | 8ms | 2.5ms |
六、风险与注意事项
6.1 Cache 不命中导致性能波动
在业务高峰期,确保 Cache Pool 容量足够容纳热数据,否则可能出现抖动。
6.2 RAID 与 LVM 叠加
如果底层还有 RAID(如 mdadm RAID10),务必先确认 RAID 性能,再在其上设计 LVM。
6.3 文件系统选择
- XFS:大并发随机写更平稳。
- EXT4:成熟稳定,但在大并发下略逊于 XFS。
七、总结
通过本次 LVM 优化实践,我们实现了:
✅ 读写性能显著提高 :IOPS 提升 2--3 倍
✅ 延迟大幅降低 :99th 延迟降低到 2.5ms
✅ 对业务零停机 :在线扩容、动态调整
✅ 易于扩展:支持未来更多 NVMe 加入条带组
对于香港服务器这样延迟敏感、大并发数据库环境,合理利用 LVM 的高级特性,不仅能提升单机性能,还能为后续分库分表、主备切换等架构演进打下扎实基础。