在 NVMe SSD 与 SATA SSD 混合集群中,如何为不同挂载点设置“io_priority”?
解读
国内中大型 CouchDB 集群为了成本与性能平衡,常把热分片放在 NVMe SSD(如 /data/nvme),冷分片放在 SATA SSD(如 /data/sata)。
CouchDB 自身没有“io_priority”参数,但 Linux 内核的 I/O 调度器与 cgroup v2 可以给不同挂载点打标签,从而间接影响 CouchDB 的磁盘优先级。
面试官想确认两点:
- 你是否知道 CouchDB 不直接管 I/O 优先级;
- 你是否能把 OS 层手段与 CouchDB 进程/容器绑定,做到可灰度、可回滚、可观测。
知识点
- cgroup v2 io.max / io.weight:blkio 控制器,按设备权重或上限限速。
- systemd slice:把
couchdb@.service放进自定义 slice,自动继承 io.weight。 - udev 规则:给 NVMe 与 SATA 盘写不同
TAG+="couchdb_fast"/TAG+="couchdb_slow",systemd 可自动绑定 slice。 - CouchDB 配置
couchdb段:database_dir与view_index_dir指向不同挂载点,不改源码即可分离冷热数据。 - node_local.ini 灰度:国内习惯按机房+机架维度做白名单发布,先灰度 5% 节点。
- 监控:用
node_exporter采集cgroup blkio.io_service_bytes_recursive,配合 Grafana 看 P99 磁盘延迟是否下降。
答案
步骤如下,全部在不改 CouchDB 源码的前提下完成:
- 分区挂载
mkfs.xfs -f /dev/nvme0n1p1 -L couchdb_nvme mkfs.xfs -f /dev/sdb1 -L couchdb_sata mount -L couchdb_nvme /data/nvme mount -L couchdb_sata /data/sata - 创建 systemd slice
# /etc/systemd/system/couchdb-fast.slice [Slice] IOWeight=1000 # /etc/systemd/system/couchdb-slow.slice [Slice] IOWeight=100 - 重写 CouchDB service
# /etc/systemd/system/couchdb@.service.d/io.conf [Service] Slice=couchdb-fast.slice Environment=COUCHDB_DATABASE_DIR=/data/nvme Environment=COUCHDB_VIEW_DIR=/data/nvme # 对冷数据节点用 couchdb-slow.slice 并指向 /data/sata - 绑定 udev 规则(可选自动化)
echo 'SUBSYSTEM=="block", ENV{ID_FS_LABEL}=="couchdb_nvme", TAG+="systemd", ENV{SYSTEMD_WANTS}+="couchdb-fast.slice"' > /etc/udev/rules.d/99-couchdb-io.rules - reload & restart
systemctl daemon-reload
systemctl restart couchdb@node1
- 验证
确认 NVMe 权重 1000,SATA 权重 100,且 CouchDB 进程已迁入对应 slice。systemd-cgtop -b /couchdb-fast.slice cat /sys/fs/cgroup/couchdb-fast.slice/io.weight
至此,不同挂载点的 io_priority 通过 cgroup weight 实现,CouchDB 无感知,运维可灰度、可回滚。
拓展思考
- 如果集群使用 K8s + CRD 部署 CouchDB,可用 io.class=“couchdb-fast” 的 StorageClass,配合 kubelet 的 TopologyManager 把 NVMe 节点打标签,再用 pod annotation io.couchdb/weight: "1000" 自动注入 slice。
- 当 SATA 盘出现 高延迟毛刺 时,可临时把 io.max 从 “0 0” 改为 “20971520 0”(约 80 MB/s 限速),10 秒级热生效,无需重启 CouchDB。
- 国内金融合规要求审计留痕,可把
systemd-journald的 cgroup 事件打到 Kafka,再入 ElasticSearch,实现“谁在什么时间改了哪块盘的 io.weight”全程可追溯。