Skip to content

存储方案技术指南

本地磁盘 · 共享存储 · 对象存储 — 适用场景分析与私有化部署实践


一、三种存储类型介绍

1.1 本地磁盘(Local Disk)

直接插在服务器上的硬盘(HDD/SSD)。程序通过文件系统路径读写,例如 /data/uploads/file.bin,是最原始、最快速的存储方式。

核心特征:

  • 读写速度最快:SSD 顺序读写可达 500MB/s ~ 7000MB/s(NVMe)
  • 零网络开销:数据不走网络,延迟极低
  • 运维最简单:无需额外组件,操作系统自带支持
  • 容量受限:只能用本机插的磁盘容量
  • 无法多机共享:其他机器无法直接访问

适用场景:

  • 单机部署:算法服务和文件在同一台机器
  • 性能敏感型计算:建模、渲染等大文件 I/O 密集任务
  • 临时中间文件存储:算法处理过程中的中间结果

1.2 共享存储(Shared Storage / NFS)

共享存储本质上还是磁盘,只是通过网络协议(最常见的是 NFS — 网络文件系统)把一台机器上的磁盘「挂载」给局域网内其他机器使用。挂载完成后,其他机器看起来就像访问本地磁盘一样。

核心特征:

  • 多机共享同一份数据:A 机器写入,B 机器立即能读到
  • 对程序透明:程序只看到普通路径,感知不到网络
  • 速度取决于内网带宽:万兆内网下读写可达 1GB/s 以上
  • 单点故障风险:NFS 服务器挂了,所有挂载机器都受影响
  • 运维复杂度中等:需要配置 NFS 服务端和客户端挂载

工作原理示意:

机器A(NFS服务端):真实磁盘在这里,/data/ 目录对外共享
机器B(NFS客户端):执行 mount 命令后,/data/ 看起来和本地一样
机器C(NFS客户端):同上,三台机器读写的是同一份数据

适用场景:

  • 多台算法机器需要访问同一批原始文件
  • 前端上传服务和算法服务分布在不同机器
  • 客户现场局域网内多机协作部署

1.3 对象存储(Object Storage)

对象存储是一种通过 HTTP API 访问的存储服务,没有文件夹层级概念,每个文件(对象)通过唯一的 Key 访问。MinIO 是目前最流行的开源私有化对象存储,兼容 AWS S3 API。

核心特征:

  • 通过 HTTP API 读写:PUT 上传,GET 下载,支持任何编程语言
  • 天然支持多端访问:前端、后端、算法服务都可以直接访问
  • 支持海量文件:单桶可存数亿个文件
  • 自带权限和 URL 签名:可生成临时访问链接,安全可控
  • 读写有网络开销:本机访问也要走 HTTP,相比本地磁盘有延迟
  • 大文件下载慢:34G 文件走网络下载耗时明显

适用场景:

  • 文件需要被多端(前端浏览器、移动端、后端)访问
  • 最终结果文件的在线分发:生成模型后提供下载链接
  • 文件量大、需要生命周期管理(自动过期清理)
  • 跨机房、跨网络的文件传输中转

二、三种存储横向对比

对比维度本地磁盘共享存储 (NFS)对象存储 (MinIO)
读写速度最快(GB/s 级)快(取决于内网)较慢(HTTP 开销)
多机共享❌ 不支持✅ 支持✅ 支持
HTTP 在线访问❌ 需要额外配置❌ 需要额外配置✅ 原生支持
大文件传输本地 IO 极快内网传输快下载是瓶颈
运维复杂度最低中等中等
私有化部署最简单需配置 NFS需部署 MinIO
适合存什么原始文件、中间结果多机共享原始文件结果文件、对外分发

三、我们项目的实际问题与优化方案

3.1 当前链路的问题

当前实现的文件流转链路如下:

前端上传 → MinIO 存储 → 算法服务从 MinIO 下载(34G)→ 跑建模算法 → 结果回传 MinIO

核心瓶颈在于:算法服务需要把 34G 的原始文件从 MinIO 通过网络下载到本地才能处理。当前部署在公网服务器上,带宽有限,这一步耗时极长且无意义——数据完全可以直接到达算法服务器。

3.2 优化目标

  • 省去算法从 MinIO 下载大文件这一步
  • 前端上传后,文件直接在算法服务器本地可用
  • 算法跑完,结果文件能通过在线地址访问
  • 方案要支持私有化部署到客户现场(单机或局域网多机)

3.3 推荐方案:前端直传算法服务器 + Nginx 静态服务

优化后的链路:

前端分片上传 → 算法服务器本地磁盘(/data/uploads/)→ 跑建模算法 → 结果写入 /data/outputs/ → Nginx 对外提供 HTTP 访问

上传组件选型:tusd

tusd 是基于 tus 断点续传协议的开源上传服务器,Go 语言编写,单一二进制文件,零依赖。

  • 支持超大文件断点续传(断网、刷新页面不影响,自动续传)
  • 文件直接写到算法服务器本地磁盘
  • 支持上传完成后触发 HTTP 回调,自动通知算法开始建模
  • 私有化部署只需拷一个二进制文件

启动命令(一行搞定):

bash
./tusd -upload-dir /data/uploads -port 1080 -hooks-http http://localhost:8000/on-upload-complete

前端代码示例(tus-js-client)

javascript
import * as tus from 'tus-js-client'

const upload = new tus.Upload(file, {
  endpoint: 'http://算法服务器IP:1080/files/',
  chunkSize: 50 * 1024 * 1024,   // 50MB 一片
  retryDelays: [0, 3000, 5000],   // 失败自动重试
  onSuccess: () => {
    // 上传完成,通知后端触发建模
  }
})
upload.start()

结果文件在线访问:Nginx 静态服务

算法跑完把结果写到 /data/outputs/,Nginx 直接伺服该目录:

nginx
server {
    listen 80;
    location /outputs/ {
        alias /data/outputs/;
    }
}

结果访问地址示例:http://服务器IP/outputs/任务ID/model.glb

💡 前端只和 HTTP 接口打交道。无论后端用本地磁盘、NFS 还是 MinIO,前端代码一个字不用改。换存储方案是纯运维层面的事。


四、不同部署场景下的存储选型建议

场景一:当前公网服务器(过渡阶段)

环节存储方案说明
原始文件上传本地磁盘前端直传 tusd,文件落到 /data/uploads/
算法读取本地磁盘算法直接读同一路径,零网络开销
结果文件访问Nginx 静态服务结果写到 /data/outputs/,Nginx 对外暴露
是否需要 MinIO可完全去掉,减少中间层

场景二:私有化单机部署(最常见)

客户现场就一台服务器,所有服务都在这台机器上。

环节存储方案说明
原始文件上传本地磁盘tusd 接收,写到本机 /data/uploads/
算法读取本地磁盘同机直接读,速度等于磁盘 IO 速度
结果文件访问Nginx 静态服务本机 Nginx 暴露 /data/outputs/
是否需要共享存储单机无需 NFS
是否需要 MinIO可选如需精细权限管理可加,否则不必要

💡 单机部署是私有化交付最简单的形态。整套方案只有 tusd + Nginx,拷两个二进制文件、改两个配置,30 分钟内完成交付。

场景三:私有化局域网多机部署

客户现场有多台机器,上传服务和算法服务分别部署在不同机器,或算法服务水平扩展到多台机器。

环节存储方案说明
原始文件上传NFS 共享存储上传服务写到 NFS,算法机器挂载同一 NFS
算法读取NFS 共享存储算法机器挂载后,路径看起来和本地一样
结果文件访问Nginx + NFS 或 MinIO结果写 NFS,任一机器 Nginx 可访问
是否需要 MinIO可选若需精细 URL 权限控制可引入

⚠️ NFS 存在单点故障风险。如客户对高可用有要求,可考虑 Ceph 分布式存储替代 NFS,但运维复杂度显著增加,一般私有化项目不推荐。

场景四:结果文件需要精细权限控制

如果结果文件需要按用户、按任务控制访问权限,或需要生成临时下载链接(比如链接 24 小时后过期),这时才真正需要引入 MinIO。

需求方案说明
公开访问结果Nginx 静态服务最简单,无需认证
按用户控制访问后端生成签名 URL后端校验权限后返回带签名的下载地址
临时访问链接MinIO Presigned URL链接自带过期时间,安全且灵活
精细 ACL 权限MinIO + 后端鉴权适合 SaaS 场景,私有化一般用不到

五、总结决策表

根据实际部署场景快速选型:

部署场景原始文件存储结果文件访问是否需要 MinIO
公网单机(当前)本地磁盘 + tusdNginx 静态服务
私有化单机本地磁盘 + tusdNginx 静态服务
私有化多机局域网NFS 共享存储Nginx + NFS可选
需要临时链接/权限任意存储MinIO Presigned URL
结果需公网分发任意存储MinIO / CDN

核心原则:

  • 能用本地磁盘就不引入网络存储——速度最快,运维最简单
  • 多机协作首选 NFS——对程序透明,改动最小
  • MinIO 只在真正需要 HTTP 分发或权限控制时才引入
  • 前端永远只和 HTTP 接口打交道,存储层换不换对前端代码没有任何影响

💡 私有化部署的核心原则是「够用即可」。引入每一个额外组件都意味着更多的运维负担和故障点。从最简单的方案开始,按需演进。

Released under the MIT License.