Skip to content

全闪存储性能调优

调优方法论

性能调优三步法:

1. 建立基准(Baseline)
   先测量当前性能,有了基准才能评估优化效果

2. 识别瓶颈(Bottleneck)
   找到限制性能的关键因素

3. 针对性优化(Optimize)
   针对瓶颈进行优化,验证效果

存储控制器调优

缓存策略

H3C 全闪存储缓存配置:

写缓存(Write Cache):
  Write-Back(回写):数据先写缓存,异步刷盘
    优点:写性能高
    风险:掉电可能丢数据(需 UPS 保护)
    适用:有 UPS 保护的生产环境
  
  Write-Through(直写):数据同时写缓存和磁盘
    优点:数据安全
    缺点:写性能较低
    适用:对数据安全要求极高的场景

读缓存(Read Cache):
  自适应读缓存:根据访问模式自动缓存热数据
  预读(Read-Ahead):顺序读时预取后续数据

RAID 策略选择

不同 RAID 级别性能对比(全闪场景):

RAID 5(4+1):
  读性能:优秀(5 块盘并行读)
  写性能:良好(有写惩罚,需计算校验)
  空间利用率:80%
  适用:读多写少

RAID 6(4+2):
  读性能:优秀
  写性能:一般(双校验写惩罚更大)
  空间利用率:67%
  适用:大容量,对安全性要求高

RAID 10(4+4):
  读性能:最优(镜像读)
  写性能:最优(无校验计算)
  空间利用率:50%
  适用:核心数据库,性能优先

H3C RAID-TP(8+3):
  三盘容错
  空间利用率:73%
  适用:大容量 HDD 阵列

主机端调优

Linux 系统调优

bash
# /etc/sysctl.conf 存储相关优化

# 增大文件描述符限制
fs.file-max = 1000000

# 调整 I/O 调度
# 对于 NVMe SSD,使用 none 调度器
# 对于 SAS SSD,使用 mq-deadline

# 网络缓冲区(iSCSI/NVMe-oF 场景)
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
net.ipv4.tcp_rmem = 4096 87380 134217728
net.ipv4.tcp_wmem = 4096 65536 134217728

# 禁用透明大页(数据库场景)
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag
bash
# 批量设置所有 NVMe 设备调优
for dev in /sys/block/nvme*; do
    # I/O 调度器
    echo none > $dev/queue/scheduler
    # 队列深度
    echo 1024 > $dev/queue/nr_requests
    # 关闭预读(随机 I/O 场景)
    echo 0 > $dev/queue/read_ahead_kb
done

# 批量设置所有 SAS SSD 调优
for dev in /sys/block/sd*; do
    echo mq-deadline > $dev/queue/scheduler
    echo 256 > $dev/queue/nr_requests
done

数据库存储调优

bash
# Oracle 数据库存储调优

# 1. 使用 ASM 直接管理存储(推荐)
# 避免文件系统层的额外开销

# 2. 调整 Oracle I/O 参数
sqlplus / as sysdba << 'EOF'
-- 调整异步 I/O
ALTER SYSTEM SET disk_asynch_io = TRUE SCOPE=SPFILE;

-- 调整 I/O 从服务器数量
ALTER SYSTEM SET db_writer_processes = 8 SCOPE=SPFILE;

-- 调整 I/O 奴隶进程
ALTER SYSTEM SET dbwr_io_slaves = 4 SCOPE=SPFILE;

-- 关闭文件系统缓存(使用 ASM 时)
ALTER SYSTEM SET filesystemio_options = 'SETALL' SCOPE=SPFILE;

-- 调整 redo log 大小(减少切换频率)
-- 建议:每 20-30 分钟切换一次
ALTER DATABASE ADD LOGFILE GROUP 4 SIZE 4G;
EOF
ini
# PostgreSQL 存储调优(postgresql.conf)

# 共享缓冲区(建议内存的 25%)
shared_buffers = 32GB

# 有效缓存大小(建议内存的 75%)
effective_cache_size = 96GB

# 工作内存(每个查询操作)
work_mem = 256MB

# 维护工作内存(VACUUM/CREATE INDEX)
maintenance_work_mem = 2GB

# 检查点设置
checkpoint_completion_target = 0.9
checkpoint_timeout = 15min
max_wal_size = 8GB

# 异步 I/O
effective_io_concurrency = 200  # NVMe SSD 设置高值

# 并行查询
max_parallel_workers_per_gather = 8
max_parallel_workers = 16

性能测试与基准

存储性能测试套件

bash
#!/bin/bash
# storage-benchmark.sh:全面存储性能测试

DEVICE="/dev/nvme0n1"
OUTPUT_DIR="/tmp/benchmark-$(date +%Y%m%d)"
mkdir -p $OUTPUT_DIR

echo "=== 存储性能基准测试 ==="
echo "设备: $DEVICE"
echo "时间: $(date)"

# 1. 随机读 IOPS(4K)
echo "测试 1/6: 随机读 IOPS(4K)..."
fio --name=randread-4k \
    --ioengine=libaio --iodepth=128 \
    --rw=randread --bs=4k --direct=1 \
    --size=100G --numjobs=8 --runtime=60 \
    --group_reporting --output-format=json \
    --filename=$DEVICE \
    --output=$OUTPUT_DIR/randread-4k.json

# 2. 随机写 IOPS(4K)
echo "测试 2/6: 随机写 IOPS(4K)..."
fio --name=randwrite-4k \
    --ioengine=libaio --iodepth=128 \
    --rw=randwrite --bs=4k --direct=1 \
    --size=100G --numjobs=8 --runtime=60 \
    --group_reporting --output-format=json \
    --filename=$DEVICE \
    --output=$OUTPUT_DIR/randwrite-4k.json

# 3. 顺序读带宽(1MB)
echo "测试 3/6: 顺序读带宽(1MB)..."
fio --name=seqread-1m \
    --ioengine=libaio --iodepth=32 \
    --rw=read --bs=1m --direct=1 \
    --size=100G --numjobs=4 --runtime=60 \
    --group_reporting --output-format=json \
    --filename=$DEVICE \
    --output=$OUTPUT_DIR/seqread-1m.json

# 4. 顺序写带宽(1MB)
echo "测试 4/6: 顺序写带宽(1MB)..."
fio --name=seqwrite-1m \
    --ioengine=libaio --iodepth=32 \
    --rw=write --bs=1m --direct=1 \
    --size=100G --numjobs=4 --runtime=60 \
    --group_reporting --output-format=json \
    --filename=$DEVICE \
    --output=$OUTPUT_DIR/seqwrite-1m.json

# 5. 混合读写(70/30)
echo "测试 5/6: 混合读写(70% 读,30% 写)..."
fio --name=mixed-7030 \
    --ioengine=libaio --iodepth=64 \
    --rw=randrw --rwmixread=70 --bs=4k --direct=1 \
    --size=100G --numjobs=8 --runtime=60 \
    --group_reporting --output-format=json \
    --filename=$DEVICE \
    --output=$OUTPUT_DIR/mixed-7030.json

# 6. 延迟测试(低队列深度)
echo "测试 6/6: 延迟测试..."
fio --name=latency \
    --ioengine=libaio --iodepth=1 \
    --rw=randread --bs=4k --direct=1 \
    --size=10G --numjobs=1 --runtime=60 \
    --percentile_list=50,90,99,99.9,99.99 \
    --group_reporting --output-format=json \
    --filename=$DEVICE \
    --output=$OUTPUT_DIR/latency.json

# 解析结果
python3 << 'PYEOF'
import json
import os

results = {}
output_dir = "/tmp/benchmark-$(date +%Y%m%d)"

tests = {
    "randread-4k": ("read", "iops"),
    "randwrite-4k": ("write", "iops"),
    "seqread-1m": ("read", "bw"),
    "seqwrite-1m": ("write", "bw"),
}

print("\n=== 测试结果汇总 ===")
print(f"{'测试项':<20} {'结果':<20}")
print("-" * 40)

for test_name, (rw, metric) in tests.items():
    try:
        with open(f"{output_dir}/{test_name}.json") as f:
            data = json.load(f)
        jobs = data["jobs"][0]
        if metric == "iops":
            value = jobs[rw]["iops"]
            print(f"{test_name:<20} {value:>15,.0f} IOPS")
        else:
            value = jobs[rw]["bw"] / 1024  # KB/s -> MB/s
            print(f"{test_name:<20} {value:>15,.0f} MB/s")
    except Exception as e:
        print(f"{test_name:<20} 读取失败: {e}")
PYEOF

echo ""
echo "详细结果保存在: $OUTPUT_DIR"

褚成志的云与计算笔记