19、存储与文件系统:eMMC/NVMe性能测试、RAID配置、NFS网络文件系统、日志轮转策略

说到 Jetson 平台的存储,我其实踩过不少坑。你想想看,一个边缘计算设备,既要跑模型推理,又要写日志,还得存数据。存储搞不好,整个系统就像瘸了腿的运动员——跑得再快也白搭。

这一章,咱们就聊聊 Jetson 上的存储那些事。我会把 eMMC 和 NVMe 的性能差异、RAID 怎么配、NFS 怎么挂,还有日志轮转怎么设,都掰开揉碎了讲清楚。

19.1 eMMC vs NVMe:性能差距有多大?

Jetson 系列通常自带 eMMC,比如 Nano 的 16GB,或者 Xavier NX 的 32GB。但说实话,eMMC 的读写速度也就那样——顺序读大概 200-300 MB/s,写更慢。而 NVMe SSD 呢?轻松上千 MB/s。

我习惯拿到板子后,先跑一轮性能测试,心里有个底。用 dd 命令测个大概,再用 fio 做精细测试。

19.1.1 用 dd 快速摸底

# 测试 eMMC 写性能(假设 eMMC 挂载在 /)
sudo dd if=/dev/zero of=/tmp/test bs=1M count=1024 conv=fdatasync

# 测试 NVMe 写性能(假设 NVMe 挂载在 /mnt/nvme)
sudo dd if=/dev/zero of=/mnt/nvme/test bs=1M count=1024 conv=fdatasync

这个命令会写 1GB 的数据,然后告诉你花了多久。我一般跑三次取平均值,避免偶然误差。

我的习惯: 测试前先清一下缓存:sudo sync && echo 3 | sudo tee /proc/sys/vm/drop_caches。不然测出来的数据会虚高,因为数据还在缓存里。

19.1.2 用 fio 做深度测试

dd 只能测顺序读写,但实际应用里随机读写更常见。这时候 fio 就派上用场了。

# 安装 fio
sudo apt install fio

# 随机读测试(4K 队列深度 32)
fio --name=randread --ioengine=libaio --iodepth=32 --rw=randread \
    --bs=4k --direct=1 --size=1G --numjobs=1 --runtime=60 \
    --group_reporting --filename=/mnt/nvme/fio_test

# 随机写测试
fio --name=randwrite --ioengine=libaio --iodepth=32 --rw=randwrite \
    --bs=4k --direct=1 --size=1G --numjobs=1 --runtime=60 \
    --group_reporting --filename=/mnt/nvme/fio_test

我在项目中遇到过一个问题:用 eMMC 跑模型时,日志写得太频繁,导致推理延迟抖动很大。后来把日志目录移到 NVMe 上,问题就解决了。说白了,随机 IOPS 的差距才是关键。

存储介质 顺序读 (MB/s) 顺序写 (MB/s) 4K 随机读 (IOPS) 4K 随机写 (IOPS)
eMMC (Jetson Nano) ~250 ~150 ~5000 ~3000
NVMe (Samsung 980) ~3500 ~3000 ~500000 ~400000

看到这个差距了吧?NVMe 的随机 IOPS 是 eMMC 的 100 倍。所以我的建议是:系统放 eMMC,数据和日志放 NVMe。

19.2 RAID 配置:给数据加个保险

Jetson 上做 RAID?你可能觉得有点夸张。但我在一个工业视觉项目里,客户要求数据不能丢,哪怕坏一块盘也得能恢复。那时候我就配了 RAID 1。

Jetson 的 PCIe 通道有限,一般只能接 1-2 块 NVMe。所以 RAID 0 或 RAID 1 是常见选择。

19.2.1 安装 mdadm

sudo apt install mdadm

19.2.2 创建 RAID 0(条带化,提升性能)

# 假设有两块 NVMe:/dev/nvme0n1 和 /dev/nvme1n1
sudo mdadm --create /dev/md0 --level=0 --raid-devices=2 /dev/nvme0n1 /dev/nvme1n1

# 格式化并挂载
sudo mkfs.ext4 /dev/md0
sudo mkdir /mnt/raid0
sudo mount /dev/md0 /mnt/raid0

19.2.3 创建 RAID 1(镜像,提升可靠性)

sudo mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/nvme0n1 /dev/nvme1n1

# 格式化并挂载
sudo mkfs.ext4 /dev/md0
sudo mkdir /mnt/raid1
sudo mount /dev/md0 /mnt/raid1
注意: RAID 不是备份!RAID 1 只能防硬盘故障,不能防误删或病毒。我曾经见过有人把 RAID 1 当备份用,结果 rm -rf 一下,两个盘的数据都没了。备份还是要靠 rsync 或定期快照。

19.2.4 保存 RAID 配置

# 查看 RAID 状态
sudo mdadm --detail /dev/md0

# 保存配置到 mdadm.conf
sudo mdadm --detail --scan | sudo tee -a /etc/mdadm/mdadm.conf

# 更新 initramfs
sudo update-initramfs -u

这样重启后 RAID 会自动组装。嗯,这里要注意:如果换了硬盘顺序,RAID 可能会认不出来,所以保存配置这步别省。

19.3 NFS 网络文件系统:让多台 Jetson 共享数据

在集群项目中,比如用多台 Jetson 做分布式推理,NFS 几乎是标配。你想想看,每台板子都存一份模型文件,更新起来多麻烦?用 NFS 统一管理,省心多了。

19.3.1 服务端配置(假设是 Ubuntu 主机)

# 安装 NFS 服务器
sudo apt install nfs-kernel-server

# 创建共享目录
sudo mkdir -p /srv/nfs/jetson_data
sudo chown nobody:nogroup /srv/nfs/jetson_data
sudo chmod 777 /srv/nfs/jetson_data

# 编辑 /etc/exports
echo "/srv/nfs/jetson_data *(rw,sync,no_subtree_check,no_root_squash)" | sudo tee -a /etc/exports

# 重启 NFS 服务
sudo exportfs -a
sudo systemctl restart nfs-kernel-server

19.3.2 客户端配置(Jetson 上)

# 安装 NFS 客户端
sudo apt install nfs-common

# 创建挂载点
sudo mkdir -p /mnt/nfs_data

# 挂载(假设服务器 IP 是 192.168.1.100)
sudo mount -t nfs 192.168.1.100:/srv/nfs/jetson_data /mnt/nfs_data

我习惯在 /etc/fstab 里加一行,这样开机自动挂载:

192.168.1.100:/srv/nfs/jetson_data /mnt/nfs_data nfs defaults,noatime,nolock 0 0
避坑指南: 我曾经在 Jetson 上挂载 NFS 时遇到卡死,原因是网络不稳定。后来加了 soft,intr 选项:mount -t nfs -o soft,intr,timeo=10,retrans=3。这样 NFS 挂掉时不会死等,应用层能及时感知。

19.4 日志轮转策略:别让日志撑爆你的 eMMC

Jetson 的 eMMC 空间本来就紧张,日志如果不加控制,几天就能把根分区塞满。我见过一个项目,因为日志没轮转,系统直接卡死,连 ssh 都进不去。

Linux 自带的 logrotate 就是干这个的。咱们来配置一下。

19.4.1 查看当前日志占用

du -sh /var/log/*

你会发现 /var/log/syslog/var/log/kern.log 是吃空间的大户。

19.4.2 配置 logrotate

默认配置在 /etc/logrotate.d/ 目录下。咱们可以自定义一个:

sudo nano /etc/logrotate.d/jetson_custom

写入以下内容:

/var/log/syslog
/var/log/kern.log
/var/log/debug
/var/log/messages
{
    rotate 4
    weekly
    missingok
    notifempty
    compress
    delaycompress
    sharedscripts
    postrotate
        /usr/lib/rsyslog/rsyslog-rotate
    endscript
}

解释一下关键参数:

  • rotate 4:保留 4 个轮转后的旧日志
  • weekly:每周轮转一次
  • compress:旧日志用 gzip 压缩,能省 80% 空间
  • delaycompress:延迟一次再压缩,方便查最近的问题

19.4.3 针对应用日志的轮转

如果你的应用自己写日志,比如 /var/log/myapp/*.log,可以单独配:

/var/log/myapp/*.log {
    daily
    rotate 7
    maxsize 100M
    compress
    missingok
    notifempty
    copytruncate
}

copytruncate 这个参数很实用——它先复制日志文件,再截断原文件。这样应用不需要重启,日志句柄也不会断。我在一个长期运行的推理服务里就用这个,非常稳。

注意: 如果日志写入非常频繁,copytruncate 可能会丢少量数据(截断和写入之间的间隙)。对可靠性要求极高的场景,建议用 create 模式,但需要应用支持重新打开日志文件。

19.5 本章知识体系

下面这张图总结了存储与文件系统的核心逻辑,从硬件选型到运维策略,一条线串起来:

Jetson 存储与文件系统知识体系 存储硬件 性能测试 RAID 配置 eMMC 容量小、速度慢 适合放系统 NVMe SSD 容量大、速度快 适合放数据/模型 RAID 0 / RAID 1 性能提升 / 数据冗余 mdadm 管理 NFS 网络文件系统 日志轮转策略 备份与恢复 核心原则:系统放 eMMC,数据放 NVMe,日志要轮转,关键数据要备份

说白了,存储这件事,规划比技术更重要。你提前想好什么数据放哪里、日志怎么管、要不要做冗余,后面就能少很多麻烦。我在多个项目里验证过这套思路,稳得很。

本章核心要点:

  • eMMC 适合放系统,NVMe 适合放数据和日志,性能差距在随机 IOPS 上尤其明显
  • RAID 1 能防硬盘故障,但不能防误删,备份是另一回事
  • NFS 挂载加 soft,intr 选项,避免网络问题导致系统卡死
  • 日志轮转用 logrotatecopytruncate 模式对运行中的应用最友好

公众号:蓝海资料掘金营,微信deep3321