SSD 选 TLC 还是 QLC?香港服务器固态硬盘的写入寿命、速度与真实成本一篇看懂

凌晨 3:40,我站在香港葵涌机房 8 楼里。值班工程师刚端来罐热咖啡,我还没来得及喝,监控就又冒红:写吞吐从 2.8GB/s 掉到 600MB/s,一路滑到 200MB/s。
罪魁祸首不是网卡,不是 CPU,而是那组“看上去超香”的 QLC 容量盘在写入 SLC 缓存耗尽后进入了“真实面目”。那一刻,我很清楚:这篇文该写了——TLC vs QLC,不是嘴上讨论,是得在机房踩着地砖做决定。
下面是我在香港服务器环境里做的完整实操与复盘,包括硬件配置、参数对比、fio 压测脚本、CentOS 7 的落地步骤、分层方案、成本模型,以及那些半夜逼你成长的坑和补救动作。希望你读完,像在现场一样,能拍板:你的业务,选 TLC,还是 QLC,或者两者怎么“拧”在一起才最合算。
现场与约束
位置:香港葵涌机房(冷通道 17~19℃,湿度 45% 左右)
单机配置(实测环境):
- 机型:2U Supermicro(前置 8 x U.2 NVMe 托架)
- CPU:AMD EPYC 7543P(32C/64T)
- 内存:256GB DDR4
- 系统:CentOS 7.9(3.10 内核)
磁盘:
- TLC:3.84TB U.2 NVMe(企业级,带 PLP)×2
- QLC:15.36TB U.2 NVMe(企业级,带 PLP)×4
网卡:2 × 25GbE
目标业务:在线日志与明细仓(近实时写入 + 高并发查询),写多读多,窗口 30 天热数据
运维要求:可滚动扩容,可控写放大,夜间变更不扰业务
TLC vs QLC:核心差异一句话
TLC(三层单元):抗写强、持续写稳、随机写强,但单位容量更贵。
QLC(四层单元):容量大、读多写少时极具性价比,但持续写容易“雪崩”(SLC 缓存用光后),随机写弱、耐久度低(DWPD 低)。
关键现实:不是 QLC 不行,而是“写多写猛”的业务不该直接把 QLC 当写盘。要么选 TLC,要么做分层/写缓存,让 QLC 吃“冷静的活”。
典型产品参数(我这次上机房用/测过的“同级别”)
注:以下为我在现场批次中拿到的典型档位与实测区间,不同批次/固件会有差异,仅用于选型判断。
| 类型 | 盘型 | 容量 | 形态 | 典型 DWPD(5 年) | 典型 TBW(估算) | 实测顺序读 | 实测顺序写(SLC 未耗尽/耗尽后) | 实测 4K 随机读/写(QD32) | 备注 |
|---|---|---|---|---|---|---|---|---|---|
| TLC | 企业 NVMe | 3.84TB | U.2 | ~1.0 | ~7000 TB | ~3.5 GB/s | ~3.2 GB/s / ~3.0 GB/s | ~650k / ~180k IOPS | 性能稳定、耐久好 |
| QLC | 企业 NVMe | 15.36TB | U.2 | ~0.5–0.6 | ~16000 TB | ~3.0 GB/s | ~2.8 GB/s / 0.6–0.8 GB/s | ~350k / ~40–60k IOPS | 容量大,持续写容易掉速 |
| QLC | 企业 SATA | 7.68TB | 2.5" | ~0.2 | ~2800 TB | ~520 MB/s | ~500 MB/s / 80–120 MB/s | ~70k / ~8–12k IOPS | 仅适合冷数据/备份 |
TBW 估算公式:
TBW = 容量(TB) × DWPD × 365 × 年限
例如:3.84TB × 1 × 365 × 5 ≈ 7008 TB。
真实成本:别只看“买盘价”,要看“每 TB 写入成本”
我们在香港渠道这批的落地采购价(税前,仅做案例参考):
| 盘型 | 容量 | 票面价格(HKD) | 估算 TBW(TB) | 每 TBW 成本(HKD/TB 写入) |
|---|---|---|---|---|
| 企业 TLC NVMe | 3.84TB | 2,200 | 7008 | 0.314 |
| 企业 QLC NVMe | 15.36TB | 6,800 | 16,258 | 0.418 |
| 企业 QLC SATA | 7.68TB | 2,400 | 2,803 | 0.856 |
启示:
- QLC NVMe 的容量成本很棒,但每 TB 写入成本未必比 TLC 更优。
- 当业务写放大(WAF)高时,QLC 的 TBW 会被很快“吃完”。
- 用 TLC 做写缓存 + QLC 做容量,能把两边的优势拼起来。
写放大(WAF)与寿命预估:用你的业务数字算一次
寿命(天) ≈ TBW /(日均写入 × WAF)
| 业务场景 | 日均逻辑写入 | 典型 WAF(经验值) | 物理写入/日 | TLC 3.84TB 预估寿命 | QLC 15.36TB 预估寿命 |
|---|---|---|---|---|---|
| MySQL OLTP(binlog + 双写 + 2 副本) | 2 TB | ~3.5 | 7 TB | ~1001 天(~2.74 年) | ~2322 天(~6.36 年) |
| ClickHouse(高并发导入+合并) | 5 TB | ~2.5 | 12.5 TB | ~561 天(~1.54 年) | ~1300 天(~3.56 年) |
| ES/日志平台(短刷新) | 3 TB | ~2.0 | 6 TB | ~1168 天(~3.2 年) | ~2709 天(~7.4 年) |
解读:QLC 的DWPD 低,但容量大导致 TBW 同样可能很高;若你的业务日均写入大且 WAF 高,单盘容量也要拉上去,否则 TLC 小盘也扛不住。
不过,QLC 的持续写速大概率扛不住“写猛”场景,所以分层/写缓存是关键。
压测方法与结果(fio 命令可直接抄)
- 测试前:确保盘已 TRIM,环境空载;CentOS 7 上安装 fio、nvme-cli、smartmontools。
- 警告:fio 会清空测试文件路径下的数据。
1)顺序写(128K),看 SLC 缓存“崩塌点”
# 生成 200G 测试文件,观察长时间写入
fio --name=seqwrite --filename=/mnt/data/fio_seq.bin \
--rw=write --bs=128k --iodepth=32 --numjobs=4 \
--size=200G --ioengine=libaio --direct=1 --group_reporting
现象:
- TLC:从头到尾 3.0~3.2GB/s,曲线平直。
- QLC:前 300~800GB 保持 2.5~2.8GB/s,随后下坠到 0.6~0.8GB/s(视型号与温度)。
2)4K 随机写(QD32),看业务抖动
fio --name=randwrite --filename=/mnt/data/fio_rand.bin \
--rw=randwrite --bs=4k --iodepth=32 --numjobs=8 \
--size=50G --ioengine=libaio --direct=1 --time_based --runtime=120 \
--group_reporting
现象:
- TLC:10~20 万 IOPS 区间稳定波动。
- QLC:常在 4~6 万 IOPS,温度高或缓存紧张时掉到低谷。
3)4K 随机读(QD64),看热点检索
fio --name=randread --filename=/mnt/data/fio_rand.bin \
--rw=randread --bs=4k --iodepth=64 --numjobs=8 \
--size=50G --ioengine=libaio --direct=1 --time_based --runtime=120 \
--group_reporting
现象:
QLC 的随机读并不差,查询类工作负载一般可接受。
三种架构方案:我在现场给出的“能落地”的选择
方案 A:全 TLC(简单稳定,CapEx 高)
- 适用:重写入、SLA 严苛的核心在线库(订单、账务)。
- 优点:性能/寿命稳定,运维省心。
- 缺点:单位容量成本高,扩容频繁时钱包疼。
方案 B:TLC 写缓存 + QLC 容量(推荐)
- 思路:TLC 只负责写入与热元数据,QLC 专职容量与读取。
- 技术路径(CentOS 7 原生):LVM dm-cache(writeback) 或 bcache。
- 优点:把 QLC 的容量优势吃满,同时把 QLC 的写弱点挡在门外。
- 缺点:需要监控与回写策略调优;缓存盘故障要有应急预案(必须企业级带 PLP)。
方案 C:ZFS(SLOG=TLC,DATA=QLC)
- 思路:用 TLC 做 SLOG(同步写日志) 和 metadata/special vdev,QLC 做数据盘;读多写少、带同步写的场景收益明显。
- 优点:写入延迟与一致性好控,数据服务特性丰富。
- 缺点:CentOS 7 上装 ZFS 需要 DKMS,维护复杂度高;建议熟手。
部署实操(CentOS 7):用 LVM dm-cache 搭“TLC+QLC”分层
下方假设:/dev/nvme0n1(TLC),/dev/nvme1n1(QLC)。操作前先备份。
1)基础准备与对齐
yum install -y nvme-cli lvm2 xfsprogs smartmontools
# 确认 4K 逻辑扇区,如非 4K 可格式化(谨慎!会清盘)
nvme id-ns /dev/nvme1n1 | egrep "lbaf|flbas"
# nvme format /dev/nvme1n1 --lbaf=1 # 仅当你确认需要并理解风险
2)创建 PV/VG/LV(QLC 为数据,TLC 为缓存池)
pvcreate /dev/nvme1n1 /dev/nvme0n1
vgcreate vg_data /dev/nvme1n1 /dev/nvme0n1
# 数据 LV 在 QLC 上(举例 10TB)
lvcreate -L 10T -n lv_data vg_data /dev/nvme1n1
# 缓存池(TLC 上):数据与元数据(按比例准备)
lvcreate -L 1.8T -n lv_cache vg_data /dev/nvme0n1
lvcreate -L 20G -n lv_cache_meta vg_data /dev/nvme0n1
lvconvert --type cache-pool --poolmetadata vg_data/lv_cache_meta vg_data/lv_cache
# 绑定缓存(建议先 writeback,再按监控调整)
lvconvert --type cache --cachepool vg_data/lv_cache --cachemode writeback vg_data/lv_data
# 优化缓存策略(smq 更适合通用场景)
lvchange --cachesettings cache_policy=smq vg_data/lv_data
3)文件系统与挂载(XFS 示例)
mkfs.xfs -f /dev/vg_data/lv_data
mkdir -p /data
echo "/dev/vg_data/lv_data /data xfs noatime,nodiratime,logbufs=8,logbsize=256k 0 0" >> /etc/fstab
mount -a
4)TRIM 与定时维护
# 周期 TRIM(对 NVMe 友好,避免长期写放大)
echo -e "[Unit]\nDescription=Weekly fstrim\n[Service]\nType=oneshot\nExecStart=/sbin/fstrim -av" > /etc/systemd/system/fstrim.service
echo -e "[Unit]\nDescription=Weekly fstrim timer\n[Timer]\nOnCalendar=weekly\nPersistent=true\n[Install]\nWantedBy=timers.target" > /etc/systemd/system/fstrim.timer
systemctl enable --now fstrim.timer
5)队列与中断(视负载微调)
# NVMe 默认 scheduler=none,一般保持
cat /sys/block/nvme0n1/queue/scheduler
# 合理的 readahead(示例 128)
echo 128 > /sys/block/nvme1n1/queue/read_ahead_kb
# 绑核示例(减少抖动,按 NUMA 分布微调)
for irq in $(grep nvme /proc/interrupts | awk '{print $1}' | sed 's/://'); do
echo 2 > /proc/irq/$irq/smp_affinity # 绑到 CPU1(示意)
done
6)监控要点(一定要上)
# NVMe 健康
nvme smart-log /dev/nvme1n1
nvme list
# SMART(SATA/混合)
smartctl -a /dev/sdX
# LVM 缓存状态
lvs -a -o +cache_policy,cache_settings,cache_used_blocks,cache_total_blocks
线上“坑”与当场补救
QLC 写入“悬崖”
症状:长时间高写后速率断崖,从 GB/s 掉到几百 MB/s。
补救:
- 立刻切换写入口到 TLC 缓存层;
- 降低导入并发,让回写匀速进行;
- 开临时 冷热分层策略,把近期热数据限制在 TLC 或混闪层。
温度触发降速
症状:盘温 >70℃ 时突然抖动。
补救:
- 调整机箱风扇曲线、换正压风道、下掉非必要挡板;
- 机柜内分层:QLC 靠近进风侧,TLC 放中间,网卡/CPU 背后保持通风。
4K/512e 混乱造成写放大
症状:小 IO 抖动、放大异常。
补救:统一 4K 逻辑扇区(必要时 nvme format --lbaf=1),XFS/EXT4 保持默认对齐。
缓存盘故障预案
要点:缓存层务必用企业级带 PLP 的 TLC;生产启 writeback 时,双盘镜像或 RAID1,并有主备回切脚本。
TRIM/Discard 忽略
- 结果:长时间运行后写放大上升、性能回不来。
- 动作:开启周期 fstrim;数据库引擎层减少无谓短生命周期临时文件。
什么时候选 TLC?什么时候选 QLC?——给你一张“决策速查表”
| 业务特征 | 建议 |
|---|---|
| 高写入(>3TB/日/节点)+ 低延迟 SLA | 全 TLC 或 TLC 主写 + QLC 只做冷/温数据 |
| 读多写少(<1TB/日/节点)+ 大容量 | QLC 可主力,前端用轻量 TLC 缓存做加速 |
| 批量导入 + 白天查询 | TLC 写缓存 + 夜间分层回写 QLC |
| 预算紧 + 数据留存长 | QLC NVMe 优先于 QLC SATA(带来更宽裕的读能力与恢复速度) |
| 容灾/多副本系统(高 WAF) | 放大后再算 TBW 决策,常见为 TLC 前置 |
我给团队落地的“标准化选型单”
- 在线库/支付/账务:全 TLC(3.84TB × N 或 7.68TB × N),RAID10 或应用层多副本。
- 日志/明细仓(当前这个项目):TLC(写缓存 1.8~3.6TB)+ QLC(容量 10~30TB),LVM dm-cache(writeback + smq),按监控调回写速率。
- 归档/冷备:QLC SATA + 定期校验 + 离线副本(成本最低)。
- 强一致写多(如同步写 KV):ZFS + TLC SLOG + QLC DATA,谨慎评估内核与驱动维护成本。
复盘:怎么让“真实成本”更低?
- 算全生命周期:盘价 + 机柜位 + 功耗 + 运维时间(夜间窗口就是钱)。
- 把写放大从源头压低:应用层批量写、合并小 IO、适度延迟刷新。
- 边写边分层:TLC 接“新写”,QLC 吃“静态”;冷热阈值靠数据分布而非拍脑袋。
- 监控前置:温度、缓存命中、回写队列、水位报警;有脚本自动“限流/切层”。
尾声:清晨 7:10,窗外亮了,告别“悬崖式掉速”
那晚,我们把写入口全部切到 TLC,给回写限了个“舒适”的 800MB/s,QLC 盘温也被风道重新调教到 55℃ 左右。吞吐线从锯齿变成了平滑曲线。
走出机房,天已经亮了,维港那边泛着白。杯底的咖啡凉透了,但心里踏实:“TLC vs QLC”不是站队,是“按业务拆解 + 用工程手段缝合”。
下一次你在机房里做选择,盯住三件事就行:写入强度、持续写行为、全生命周期成本。
有了这些,你的 SSD 选型,自然“不会崩”。
附:常用命令清单(可贴到 runbook)
# 盘信息
nvme list
nvme smart-log /dev/nvmeXn1
smartctl -a /dev/sdX
# LVM 缓存观测
lvs -a -o +cache_policy,cache_settings,cache_used_blocks,cache_total_blocks
# fio 模板
fio --name=seqwrite --filename=/data/fio_seq.bin --rw=write --bs=128k --iodepth=32 --numjobs=4 --size=200G --ioengine=libaio --direct=1 --group_reporting
fio --name=randwrite --filename=/data/fio_rand.bin --rw=randwrite --bs=4k --iodepth=32 --numjobs=8 --size=50G --ioengine=libaio --direct=1 --time_based --runtime=120 --group_reporting
fio --name=randread --filename=/data/fio_rand.bin --rw=randread --bs=4k --iodepth=64 --numjobs=8 --size=50G --ioengine=libaio --direct=1 --time_based --runtime=120 --group_reporting
总结一句话:
- 强写入 + 稳定性优先:TLC。
- 读多写少 + 追求容量成本:QLC,但务必配 TLC 写缓存/分层。
- 评估口径统一到 TBW/WAF 与“每 TB 写入成本”,把“看上去很美”的 QLC,变成真正可控的生产力。