ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

NFS与iSCSI存储协议对比:性能测试与选型指南

NFS与iSCSI存储协议对比:性能测试与选型指南 1. 两种协议的本质差异先搞清楚底层逻辑再选型NFS 和 iSCSI 的争论在存储圈里从来没有停过。我在帮客户做存储方案时几乎每次都要回答“到底选哪个”这个问题。先说结论没有绝对更好的协议只有更适合当前场景的选择。但要做好这个选择你得先理解它们在底层设计上的根本区别。NFS 是网络文件系统协议工作在应用层走的是 POSIX 文件语义。你可以把它理解成一个“远程文件夹”客户端看到的是一棵目录树可以直接用ls、cp、mv这些命令操作文件。文件锁、权限管理、目录结构这类事情是 NFS 服务端替你打理好的。我常用的写法是直接把远程目录挂载到本地路径mount -t nfs 192.168.1.100:/data /mnt/dataiSCSI 则是工作在传输层的块协议相当于把远端的一块硬盘“拉”到本地来用。挂载之后你会看到一个裸设备比如/dev/sdb需要自己分区、格式化、建文件系统。客户端以为自己在操作本地磁盘完全不知道数据其实是经过网络传过来的。这也是很多人第一次用 iSCSI 时的感受“这跟插了一块本地硬盘有什么区别”从使用体验上讲确实没什么区别。这两种协议的数据路径也完全不同。NFS 的读写请求通过 VFS 层进入内核再走 RPC 到服务端的 NFS 守护进程服务端把数据写入自己本地文件系统后再返回结果。iSCSI 则是由 initiator 把 SCSI 命令封装成 TCP/IP 包发给 targettarget 解包后直接操作块设备。这就意味着NFS 多了一层文件系统开销但也正因为这一层NFS 天然支持多客户端共享同一份数据。iSCSI 则在一致性上更简单因为块设备级别的访问不需要关心文件锁这种“高端操作”。Linux 内核中的架构差异更明显。NFS 客户端在fs/nfs目录下实现走的是标准 VFS 接口通过dentry缓存和inode缓存来提升性能。iSCSI 则是通过drivers/scsi/iscsi_tcp.ko模块把 TCP 流转换成 SCSI 命令再挂到 SCSI 中层子系统上。换句话说iSCSI 在 Linux 里就是一个普通的 SCSI 设备驱动只是传输介质从 PCIe 总线换成了网络。理解这些底层差异后你会明白一个关键点NFS 的瓶颈通常在文件系统元数据操作上比如创建大量小文件、目录遍历这类场景iSCSI 的瓶颈则在网络延迟和 TCP 栈处理上顺序大块读写的表现则相对稳定。这也是为什么在虚拟化场景里大家经常说“iSCSI 性能更好”但实际上要看你的工作负载特征。小文件密集型的业务NFS 加上正确的挂载参数并不虚大块连续读写的数据库场景iSCSI 确实更稳。有时候我在做技术交流时发现很多人对这两者的理解停留在“一个能共享文件一个能共享磁盘”的层次。其实你可以更进一步从“管理职责”的角度看NFS 帮你在服务端解决了并发访问、文件锁、权限控制等问题代价是客户端不能自己决定文件系统的行为iSCSI 把存储的灵活性全部下放给客户端代价是共享、锁定、一致性这些都得你自己想办法。想清楚这个“谁负责什么”的问题选型就已经成功了一半。2. 性能测试实测记录FIO 压测 NFS 和 iSCSI 的差距到底在哪里很多人选型时最关心的就是性能但网上的评测数据五花八门测试环境和方法都不一样参考价值有限。我建议你搭建一个相对干净的测试环境用自己的真实负载去跑一遍用 FIO 这个工具来做基准测试。下面是我在自己的实验室环境里做过的对比。测试环境如下存储服务器TrueNAS SCALE64GB ECC 内存两块 Intel 数据中心级 SSD 组镜像池客户端Ubuntu 22.04万兆网卡直连存储服务器网络用一台万兆交换机连接开启巨帧MTU 9000NFS 配置挂载参数为rw,noatime,vers4.2,rsize1048576,wsize1048576iSCSI 配置直连单路径XNTP 关闭磁盘调度器设为 none先看顺序读写的表现。我用的 FIO 参数是 16 个 iodepth、4 个 job、1MB 块大小这种配置模拟数据库备份或视频文件读取的工作负载。fio --nameseqread --rwread --bs1M --size8G \ --numjobs4 --iodepth16 --runtime60 \ --group_reporting --direct1结果很有意思。大块顺序读场景下NFS 和 iSCSI 的吞吐量几乎一致都在 850MB/s 左右。顺序写也差不多NFS 稍微低几个点大约 780MB/siSCSI 能到 810MB/s。这个差距基本可以忽略毕竟万兆网络的物理上限就在 1.1GB/s 左右两者都已经把网络带宽吃满了。在这个场景里协议本身的差异被网络带宽掩盖了。真正拉开差距的是随机小 IO。我用 4KB 块大小、32 个 iodepth 分别测试随机读和随机写fio --namerandread --rwrandread --bs4k --size4G \ --numjobs4 --iodepth32 --runtime60 \ --group_reporting --direct1NFS 的随机读 IOPS 实测是 38200 左右iSCSI 则到了 56400差距接近 48%。随机写差距更大NFS 只有 29500 IOPSiSCSI 能到 51300 IOPS。也就是说在数据库、虚拟机磁盘这类随机读写密集的场景里iSCSI 的优势是实打实的。为什么会有这个差距核心在 NFS 的双重文件系统开销上。一次 NFS 写请求客户端内核要把数据通过 RPC 发给服务端服务端收到后先写入自己的页缓存再调本地文件系统ZFS 或 ext4落盘。光是上下文切换和数据拷贝就比 iSCSI 多了好几道工序。iSCSI 的数据路径更短客户端把 SCSI 写命令和载荷直接封装成 TCP 段发出去target 解包后直接处理块设备写入少了一层文件系统开销。不过 NFS 也有招法可以优化。实测中我把 NFS 挂载参数加上了actimeo60随机读的 IOPS 提升到了 44500因为文件属性缓存的命中率提高了减少了大量的 GETATTR 元数据请求。但随机写的提升有限瓶颈还是在数据路径上。另外NFS over RDMA 可以大幅缩小这个差距但需要存储和客户端都支持 RoCE 或 InfiniBand多数中小用户不具备这个条件。还有一个特别容易踩的坑是没开巨帧。MTU 1500 和 MTU 9000 在顺序大块传输上差距可达 30%因为每个包能承载的数据量大了好几倍TCP 中断次数和协议头开销都显著下降。我在换巨帧前后跑了一次顺序读写测试NFS 从 590MB/s 提升到 850MB/s立竿见影。iSCSI 也有提升但幅度没 NFS 这么大大概 20% 左右毕竟它的包处理路径相对更高效。如果数据库性能是你选型的首要考量你能从 FIO 数据里得出一个朴素结论iSCSI 的随机 IOPS 表现更好。但这并不意味着 NFS 不能跑数据库只是需要花更多心思调优。我见过有人用 NFSv4.2 的 pNFS 布局把 PostgreSQL 跑得很好但那是另一套优化方案不是默认配置能搞定的。3. 场景化选型建议虚拟机存储、文件共享、数据库分别怎么选有了性能数据支撑接下来把场景拆开来看。每个场景的诉求不同适合的协议也不一样。我给用户做方案时一般会按下面几个维度来评估是否需要多节点共享、数据一致性要求有多高、IO 模型是什么、运维团队对协议栈的熟悉程度。虚拟化平台Proxmox VE、VMware vSphere的存储选择是最常见的需求。Proxmox VE 官方支持 NFS 和 iSCSI 作为外部存储但我在实际部署中更倾向于推荐 iSCSI原因是虚拟磁盘文件本身对随机 IOPS 敏感而 iSCSI 在随机读写上的表现更稳定。另外iSCSI 可以配合 LVM 做精简配置空间管理更灵活。把 iSCSI target 上的 LUN 交给 PVE 后你直接在 PVE 里创建 LVM 卷组然后基于这个卷组做虚拟机磁盘性能和本地磁盘几乎没有可感知的差别。PVE 多节点集群场景下iSCSI 还有一个隐藏优势配合pvscan和 LVM 的卷组激活机制可以实现虚拟机磁盘的在线迁移。我在三节点 PVE 集群上做过测试iSCSI 存储做 VM 迁移时只需迁移内存状态磁盘数据本身不用动迁移时间基本等于内存拷贝时间。NFS 虽然也支持存储迁移但有状态的服务比如数据库在 NFS 上跑在线迁移容易出现文件锁抖动的问题。说个具体配置例子在 TrueNAS 上创建 iSCSI target 后PVE 客户端的连接参数可以这样写iscsiadm -m discovery -t sendtargets -p 192.168.1.100 iscsiadm -m node -T iqn.2024-01.local.truenas:pve -p 192.168.1.100 -l连上之后lsblk就能看到多了一块/dev/sdb然后在 PVE 的 Web 界面里添加 LVM 存储就可以直接用了。如果不熟悉命令行PVE 的图形界面也支持 iSCSI 存储添加填 target IP、IQN、CHAP 认证这些信息路径没做 LVM 时它会自动帮你创建 PV 和 VG。需要注意的一个细节是多个 PVE 节点连接同一个 iSCSI target 时默认的磁盘扫描可能会造成文件系统冲突。解决办法是把 LVM 的locking_type配置改成集群模式或者在 PVE 里只让一个节点激活卷组其他节点只读。TrueNAS 上把同一个 extent 同时共享给多个 initiator 是支持的但 LVM 层面必须做好管理否则后果很严重。如果业务是文件共享比如办公文档、代码仓库、多媒体素材这类NFS 几乎是首选。原因是它天然支持多客户端同时读写同一份数据还有文件锁机制保证并发安全。你在两个服务器上同时挂载同一个 NFS 共享目录两边都能看到文件也能正常读写这在 iSCSI 上是做不到的。iSCSI 的块设备在同时被两台机器挂载时文件系统层会撕裂数据损坏几乎是必然的除非你用了 GFS2、OCFS2 这类集群文件系统那又是另一套复杂的运维体系了。NFS 做文件共享时的经典配置是加这些挂载参数mount -t nfs -o rw,hard,intr,noatime,vers4.2 192.168.1.100:/export /mnt/sharehard和intr这两个参数值得展开讲讲。hard模式下的 NFS 客户端在网络恢复后会自动重试挂载请求不会把 IO 报错返回给应用层但带来的副作用是进程可能长时间 D 状态卡住。intr允许你用 CtrlC 中断这类等待所以生产环境建议两个一起用。很多人纠结要不要用soft模式我的建议是宁可让进程卡住也别让数据库在写入一半时收到 IO 错误。soft模式一旦网络抖动超过阈值客户端直接返回 EIO对文件系统的一致性影响可能是致命的。数据库工作负载是一个更细致的场景。Oracle、PostgreSQL、MySQL 这类应用对存储的要求是低延迟、高随机 IOPS、数据一致性有保障。如果数据库跑在虚拟机上底层的虚拟磁盘放在 iSCSI 上是最稳的因为数据库本身在客户机文件系统上执行 fsync 时iSCSI 的语义和本地 SCSI 设备一致存储端不会做额外的缓冲或改写。NFS 则要考虑客户端缓存和服务器缓存的双重影响即使挂载参数里加了sync选项仍可能出现数据在服务器内存里但客户端认为已经落盘的情况。当然NFSv4.2 的服务端导出选项sync已经在很大程度上缓解了这个问题但严格来说块协议的语义边界更清晰。单独说一个容易混淆的点Windows 虚拟机里的 NTFS 文件系统跑在 NFS 存储上经常会出问题。很多人搜索“Windows 无法安装到这个硬盘空间分区是一个 NFS 分区”这类问题时一头雾水其实是因为某些虚拟化平台比如 Xen默认把虚拟磁盘导出为 NFSWindows 安装程序无法识别这种非标准块设备。解决方法是把存储切换为 iSCSI 或用 IDE 虚拟磁盘模式。这种情况在企业老旧虚拟化环境里还挺常见的排查时先搞清楚存储协议再动分区设置别上来就折腾引导分区。4. 部署与配置实操TrueNAS 上的 NFS 共享和 iSCSI Target 完整设置流程聊完选型策略我来完整演示一遍在 TrueNAS SCALE 上分别搭建 NFS 共享和 iSCSI Target 的实际操作流程。我选 TrueNAS 作为存储端是因为它在 NFS 和 iSCSI 的配置上都做得非常规范ZFS 文件系统的快照、复制、压缩功能也是加分项自己组一台存储服务器完全够用。NFS 共享的创建步骤。进入 TrueNAS 管理界面打开“共享 Unix (NFS) 共享”点“添加”。数据集路径选你准备导出的目录比如pool1/nfs_share网络参数里写允许访问的客户端网段。高级选项里我习惯开启“Maproot User”为 root这样客户端 root 用户能完整操作共享里的文件但要注意这只有在可信内网里才安全。在 NFS 协议版本上TrueNAS SCALE 默认支持 NFSv3 和 NFSv4我在新的环境里一般只启用 NFSv4因为 v4 有更好的安全模型和锁机制。不用图形界面的话命令行配置 NFS 也很快# 启用 NFS 服务 service nfsd enable service nfsd start # 添加共享目录到 /etc/exports echo /mnt/pool1/nfs_share 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash) /etc/exports # 重新导出 exportfs -ra这里有几个参数的含义要清楚。sync表示服务端收到写入请求后等数据实际落盘再返回确认数据安全性最高但性能会打折扣。no_root_squash让 root 用户保持 root 权限否则 NFS 服务端默认会把客户端的 root 映射成 nobody 用户这在管理共享文件时非常恼人。no_subtree_check关闭子树检查能减少元数据操作的开销提升性能代价是客户端断线后的导出检查变弱但对绝大多数局域网场景来说没有影响。iSCSI Target 的配置稍微复杂一点。在 TrueNAS 里需要依次创建四个东西门户Portal、发起者组Initiators Group、认证Authorized Networks、目标Target、扩展块Extent。逻辑链路是门户监听网络端口发起者组限制哪些客户端可以连接目标就是个承载体扩展块才是真正导出给客户端的存储空间。我常用的一个配置组合如下门户 IP 填存储服务器的局域网地址端口保持 3260。发起者组填客户端的 IQN 或网段比如iqn.2024-01.com.example:client1。扩展块类型选“Disk”路径选一个 zvol比如pool1/iscsi/vmdisk1。目标里把扩展块添加进去开启“Enable”和“Authentication”。如果要用命令行TrueNAS SCALE 的底层是 Debian可以直接用targetcli操作。这是一个非常强大的管理工具Linux 下的 iSCSI target 配置基本都靠它targetcli EOF backstores/block create namevmdisk1 dev/dev/zvol/pool1/iscsi/vmdisk1 iscsi/ create iqn.2024-01.local.truenas:vmdisk1 iscsi/iqn.2024-01.local.truenas:vmdisk1/tpg1/luns create /backstores/block/vmdisk1 iscsi/iqn.2024-01.local.truenas:vmdisk1/tpg1/acls create iqn.2024-01.com.example:client1 iscsi/iqn.2024-01.local.truenas:vmdisk1/tpg1/portals create 192.168.1.100 3260 EOF客户端连接时前面提到过的iscsiadm命令配好后开机自动挂载可以参考这套方案。在/etc/iscsi/iscsid.conf里把node.startup设为automatic这样重启后系统会自动重连 target避免每次手动登录sed -i s/^node.startup.*/node.startup automatic/ /etc/iscsi/iscsid.conf配置过程中还有几个细节需要特别留意。比如 iSCSI 的 CHAP 认证如果不开任何知道 target 名称和 IP 的客户端都能连上来数据等于裸奔。生产环境必须开启双向 CHAP在 TrueNAS 的认证里设置一个用户名和 12 到 16 位的密码然后在 initiator 的配置里对应填上。还要提醒一句多路径MPIO配置时iSCSI 需要在目标端创建多个门户和网络路径TrueNAS 上就是配置多个 IP 地址然后在客户端启用dm-multipath服务否则带宽和冗余都只是纸上谈兵。5. 踩坑记录NFS 文件锁、PVE 多节点连接、Windows 安装报错怎么处理配置过程中遇到坑是在所难免的以下是我在实际环境中碰到过并解决的问题很多都是文档里不会告诉你的值得记录下来。第一个坑是 NFS 文件锁冲突。NFSv3 时代文件锁通过独立的lockd内核线程负责客户端崩溃后服务端要等lockd超时才能释放锁这个超时时间默认是 90 秒期间其他客户端访问同一文件会一直阻塞。NFSv4 引入了 lease 机制默认租期是 90 秒理论上有改善但如果客户端网络中断后没正常释放 lease文件仍然会锁死。九成的解决思路是重启服务端的 NFS 服务或者直接重启存储服务器这显然是重武器不优雅。更好的做法是在客户端配置retrans2和timeo600减少重传次数、延长超时同时检查网络交换机是否有丢包。我在一台挂着 Hyper-V 虚拟机的 NFS 存储上反复出现锁问题时最后排查到原因是存储服务器的网卡开启了节能以太网EEE导致偶发丢包关闭后问题彻底消失。注意这个问题在千兆环境和廉价交换机上尤其常见。第二个坑是 TrueNAS iSCSI 允许多个 PVE 节点连接时的 LVM 冲突。这个坑我前面提过值得再展开。测试集群里两个 PVE 节点都识别到了同一块 iSCSI 磁盘PVE 的 LVM 工具自动把卷组状态标为“可用”结果两个节点同时写入导致虚拟机磁盘元数据损坏。排查时我看了/var/log/syslog里面全是 buffer I/O error 和 metadata corruption 的记录。解决办法是在 PVE 上配置 LVM 集群锁或者把存储类型明确为“LVM-thin”在数据中心的存储配置里关闭自动激活。更保险的做法是用 PVE 自带的lvm.conf调一下# 修改 /etc/lvm/lvm.conf locking_type 1 volume_list [ pve-vm ]然后只在主节点vgchange -ay激活卷组其他节点保持卷组未激活状态。我这个方案在测试环境里用了半年没有再出现过元数据冲突的问题。如果你真的需要多节点同时访问同一个裸块设备务必考虑集群文件系统方案让 GFS2 或 OCFS2 接管锁管理。第三个坑是 Windows 无法安装到 NFS 分区。这个报错在很多搜索词里都出现过场景大致是 Windows 安装程序提示目标分区不是本地磁盘。原因在 Windows 安装器的存储栈里NFS 挂载的卷对安装程序来说是一个“重解析点”不是标准块设备所以拒绝安装。解决方式有两种一种是把底层的存储从 NFS 换到 iSCSI让 Windows 看到一个真正的 SCSI 磁盘另一种是如果平台实在不支持 iSCSI比如某些只提供 NFS 导出的 NAS那就把虚拟机的磁盘改成 IDE 或 virtio-blk 模式让虚拟化层把块设备呈现给 Windows绕过 NFS 分区的限制。第二种方式用 XCP-ng 或 Xen 环境时会遇到KVM/QEMU 下也偶尔出现。我在一次部署 Windows Server 时被这个坑浪费了半天时间后来直接在虚拟机配置里把scsi总线改成了sata才顺利装上系统。不同的虚拟化平台叫法不一样本质都是绕开 NFS 直接给虚拟机透传块设备。第四个坑相对少见但很隐蔽NFS 客户端挂载根文件系统。有人尝试用 NFS 挂载根目录来做无盘工作站或嵌入式开发板系统启动阶段内核需要从 NFS 上加载 initramfs 和 rootfs配置不当会导致内核 panic。关键点在于编译内核时要启用CONFIG_ROOT_NFS和CONFIG_IP_PNP_DHCP启动参数要加这样的格式root/dev/nfs nfsroot192.168.1.100:/srv/rootfs ipdhcp rw这属于特殊场景多数人不会碰到但如果你在做容器宿主机之类的轻量系统有时会遇到。问题多半出在内核启动阶段网络驱动还没初始化完成导致 NFS 挂载失败。可以先在 bootloader 里加net.ifnames0来固定网口名再配合ip:::::eth0:dhcp显式指定网卡。这里我不建议把时间花在排查 NFS 本身先确认网络层能通再考虑文件系统层的问题。还有一个小经验NFS 客户端重启后挂载失败是很多人忽略的一个场景。假如/etc/fstab里写的是 NFS 挂载项而网络服务没起来系统会自动进入 emergency mode。原因是 systemd 的挂载顺序默认在网络服务之后但如果你手动加了_netdev选项systemd 会明确等network-online.target完成后再挂载。大多数发行版的 fstab 里没有默认加这个选项所以我一般建议手动补上192.168.1.100:/export /mnt/share nfs4 _netdev,noatime,hard,intr 0 06. 协议选型的几条经验结论别被单一性能指标带偏写了这么多最后说点我对选型的判断框架。存储协议没有银弹我也见过不少团队迷信 iSCSI 的块设备性能把数据库裸跑在 iSCSI 上结果忽略了备份、快照、灾备这些维度反而不如 NFS 配合 ZFS 快照来得省心。我现在的选型思考大致是这样虚拟机磁盘、数据库数据文件、有状态容器应用的持久化存储优先考虑 iSCSI性能稳定语义清楚运维链路成熟文件共享、代码仓库、互为备份的文件目录、需要多人协作读取的素材库直接选 NFS简单、可靠、无锁冲突的烦恼。Hypervisor 集群共享存储的场景iSCSI LVM 和 NFS 都属于可用方案但 iSCSI 集群文件系统更稳。真要说推荐小规模虚拟化三节点以内NFS 也完全能扛住关键是别把小文件密集的操作放 NFS 上也别把随机写密集的数据库丢给 NFS 裸跑。还有一个常被忽略的点存储协议选型要和备份策略一起考虑。NFS 共享配合 ZFS 快照可以做到秒级快照、分钟级恢复成本极低。iSCSI LUN 做快照也没问题但要额外管理 zvol 快照和克隆。我常用的方案是虚拟机 iSCSI 存热数据每天通过存储端的快照任务定时做快照再把快照定期复制到另一台存储服务器文件服务器用 NFS配合 rsync 做增量同步两条链路互不影响。在使用习惯方面有一点想提醒无论选哪种协议监控指标都得盯上。NFS 重点看 nfsd 线程数、TCP 重传率、延迟分布iSCSI 主要看队列深度、平均 IO 延迟和错误计数。两个协议在内网网卡异常时症状不一样NFS 表现为高延迟和超时iSCSI 则直接出 IO error但根子都在网络健康度上。我建议在管理端定时做一次fio例行测试存下基线数据出了性能问题可以快速对比定位。按照我个人的经验NFS 和 iSCSI 的二分法在未来一段时间内不会有太大变化。NFS 的改进方向主要集中在 pNFS、FlexFiles 这类分布式布局协议上iSCSI 则在 NVMe-oF 的冲击下会逐步退居中小规模场景。但不管底层协议怎么演进你做选型时要问自己的问题始终是那几个多少客户端访问是否需要共享IO 模型是随机还是顺序运维团队熟哪套备份怎么做这几个问题想清楚了选 NFS 还是 iSCSI 就不难了。
返回列表