资讯详情

HPC场景下分布式对象存储:架构拆分、小文件聚合与性能调优

📅 2026/9/30 8:03:25 | 华诺云谱 👁 阅读
HPC场景下分布式对象存储:架构拆分、小文件聚合与性能调优
简介一份面向高性能计算场景的分布式对象存储系统学术论文PDF发表于《计算机工程》2017年围绕现有分布式文件系统数据组织低效、访问语义冗余等问题提出COSS系统通过分离数据访问与管理、使用分布式全局对象组织及基于内存的元数据管理来优化性能论文还分析了高性能计算对存储系统的挑战以及COSS在精简访问语义和元数据管理上的具体实现细节。资源适合分布式存储开发者、HPC系统研究人员以及需要专业参考文献的高校师生。包内为1个PDF文件共350KB完整收录论文全文包含系统架构、设计思路、实验对比与扩展性分析。实验数据显示COSS在大规模并发访问下读/写聚合带宽相比Lustre分别提升22.5%和50.4%文件创建、删除性能达到Lustre的2.15倍和5.13倍并表现出拟线性扩展能力已有112人学习下载可作为分布式系统设计理论依据、课题研究参考或技术选型论证材料。1. 高性能计算场景下分布式对象存储为什么是刚需气象模式跑一次实验会碾出几十万个网格文件材料模拟任务做完一轮中间结果动辄几个 TB。这类工作负载放在传统 HPC 集群里第一个想到的是并行文件系统但 Lustre 那类方案的每 GB 成本摆在那冷数据长期占着挂载点计算节点的 IO 带宽天天被日志和归档任务抢。面向高性能计算的分布式对象存储系统就是在这个夹缝里长出来的它用对象存储的桶和键模型把共享存储池从昂贵的并行文件系统里解放出来专吃高带宽吞吐、海量小文件、多租户共享这类 HPC 脏活累活。适合读这篇文章的是正在做 HPC 平台存储选型、被小文件性能折磨、或者想在 AI 训练和科学计算之间共用一套存储底座的人。这篇不讲 PPT只讲架构怎么拆、参数怎么调、坑在哪。2. 架构拆分元数据与数据分离先定数据面和元数据面2.1 HPC 文件语义与对象语义的差异先搞清楚你在替谁还债HPC 用户习惯了 POSIX 语义随机写、追加写、目录里随时 ls。对象存储的模型是桶加对象一个对象一把 HTTP 式的键整写整读覆盖写等于重建。这个语义落差是所有落地痛苦的根源。面向 HPC 的场景里常见的做法不是在存储内核里硬造 POSIX而是用一层网关把语义翻译过去。我一般会把接入方式分成三类来看第一类是纯 S3 接口适合 AI 训练的数据集读取、 checkpoint 归档这类本来就按对象组织的任务第二类是 NFS/SMB 网关把对象存储挂成传统目录适合老 MPI 作业但并发一高网关就成瓶颈只能靠多网关水平扩展硬顶第三类是 FUSE 客户端语义最接近 POSIX但内核态和用户态之间拷贝多一次小文件时延反而更难看。接入方式的取舍要写在设计文档第一页因为它决定了后面所有性能参数怎么定。如果主要负载是大文件顺序读S3 接口就够了如果用户死活要用ls和通配符那就得在网关上做目录缓存不然 list 请求能把元数据集群打穿。还有一个被低估的点对象存储的覆盖写是删旧写新HPC 任务里常见的打开文件追加一行日志这类操作在对象语义下会被放大成一次完整重写设计时就得约定好——日志这类数据走独立的并行文件系统别塞对象存储。2.2 数据面设计副本与纠删码的边界别一上来就搞 EC数据面解决的是数据放哪、怎么冗余、怎么不被单点故障干掉。HPC 场景下我见过太多团队一上来就上纠删码EC理由是省容量结果性能翻车后调了一个月。EC 的读写路径比副本重写一个对象要经过条带切分、编码计算、多节点分发读一个小对象可能要把整个条带捞出来再解码。这在顺序大文件场景里问题不大但在小对象密集的 HPC 工作负载里就是灾难。我的建议是分两层热数据层用三副本换读写性能和故障重建速度冷数据层用 EC 83省容量反正读得少。条带大小和 EC 配比要按对象大小分布来定不是拍脑袋 42。下面这张表是我做选型时常用的对照冗余策略典型配比可用容量比适用对象大小代价三副本333%小于 1MB 的热点数据写入快重建快容量浪费大EC 424266%大于 16MB 的顺序读大文件写放大 1.5 倍读放大 2 倍EC 838372%归档冷数据重建慢小对象随机读基本废EC 636366%中等文件读写比接近 1均衡但两边都不突出条带大小这个参数最容易被忽略。EC 的条带一般是几十 MB一个 4KB 的对象落在条带里读它的时候要把整个条带拉出来这就是 EC 小对象读放大的本质。所以在数据面设计时一定要按对象大小分布选策略而不是按存储容量倒推。另外条带的数据块要按故障域打散同一条带的数据块落到不同机架甚至不同机房不然交换机挂掉条带直接不可用。数据放置策略里还有一个 HPC 特有的考量计算节点和存储节点最好同构方便以后把存储进程直接部署到计算节点上做真正的存算一体。但这个方案会引入调度耦合节点宕机时存储和计算一起受影响建议只在实验环境里玩生产环境还是把数据面独立出来。2.3 元数据面独立集群是标配别把索引和数据混在一个进程里对象存储的元数据服务和 HPC 里的 Lustre MDS 地位一样都是最容易先死的那一个。元数据服务管桶列表、对象列表、对象属性每个读请求进来先查一次索引写请求要落索引再落数据。小文件场景下元数据压力比数据压力大一个数量级。面向高性能计算的分布式对象存储系统元数据面必须独立部署。常见的做法是用一个分布式 KV 集群撑索引按桶哈希分区每个分区一个 Raft 组保证强一致。桶内对象的键设计得有点讲究前缀用时间戳或者任务 ID让同一个任务的对象落在相邻分区list 的时候走顺序扫描不要用随机 UUID 做前缀那是给 KV 集群上眼药。这里有个玄学元数据集群的磁盘配置经常被忽视。KV 引擎的 WAL 写的是小 IOSSD 和 HDD 的时延差距能到十倍。我见过把元数据索引盘和 OS 盘放在一起的部署压力一起来节点心跳超时整个集群跟着抖。元数据节点的数据盘用 NVMeWAL 盘单独一块这是最不值得省的成本。2.4 网关层连接池、读缓存、写缓冲三件套网关是计算节点和存储集群之间的翻译官。S3 网关的每个请求都要做签名验证HPC 里成千上万个并发请求同时上来CPU 先被打满。所以网关层要做的第一件事是连接复用长连接池按计算节点维度开每个节点几十个连接就够别让客户端每次新建 TCP。读缓存放热门数据集比如 AI 训练反复读取的 epoch 数据缓存命中率上来后吞吐能翻好几倍。写缓冲则是把多个小对象攒成一个大块再往后端刷这是小文件场景的关键下一章专门讲。网关层还有一个容易被忽略的参数请求队列深度。队列太浅磁盘带宽吃不满队列太深时延飙升。我习惯从 64 开始调压测时盯着 P99 时延曲线出现锯齿就往下收。3. 小文件聚合与读写路径把对象存储拉到 HPC 的及格线3.1 现象先行为什么一万个小对象能把集群打跪HPC 工作负载里最常见也最头疼的就是小文件。地球物理勘探一个工区几百万个地震道每个道几 KB深度学习数据集里几万张图片每张几百 KB。对象存储处理小对象时一次读请求的完整链路是客户端签名、网络 RTT、网关鉴权、元数据索引查询、数据节点寻址、磁盘寻道、响应返回。单看一次请求没多少开销但并发上来后就不是线性增长了。元数据集群的连接数、网关的线程池、数据节点的磁盘队列任何一个环节打满整个集群的 P99 时延就开始飙升。现象就是文件数量翻一倍吞吐掉一半时延涨一个数量级。所以面向 HPC 的对象存储系统设计目标不是让单对象时延降到多低而是把单位时间能处理的对象数提上去提不上去就只能聚合。聚合的本质是摊薄开销一万个 8KB 的小文件合并成十个 8MB 的大对象请求数少了一千倍元数据索引条目少了一千倍磁盘从随机读变成顺序读。代价是牺牲单对象访问的粒度但对 HPC 任务来说数据集本来就是整体生产的聚合读写是划算的买卖。3.2 客户端侧聚合先用一个打包脚本理解粒度服务端做透明聚合是最理想的但落地复杂。客户端侧聚合则是马上能用的土办法任务跑完后把结果目录打包成 tar 段再传对象存储。下面这个脚本是我在气象数据归档场景里常用的逻辑不复杂但参数值得抄import tarfile from pathlib import Path def pack_small_files(src_dir: str, target_prefix: str, block_bytes: int 64 * 1024 * 1024): 将 src_dir 下的小文件按体积切成多个 tar 段。 block_bytes 控制单个 tar 对象的大小64MB 是万兆网络下的均衡值。 src Path(src_dir) part 0 current 0 fh tarfile.open(f{target_prefix}.part{part:04d}.tar, w) # 先排序再遍历保证多次打包结果一致方便后期校验 for file_path in sorted(src.rglob(*)): if not file_path.is_file(): continue arcname str(file_path.relative_to(src)) info fh.gettarinfo(str(file_path), arcnamearcname) with open(file_path, rb) as f: fh.addfile(info, f) current info.size if current block_bytes: fh.close() # 一个段写满就收避免单对象过大导致上传失败 part 1 current 0 fh tarfile.open(f{target_prefix}.part{part:04d}.tar, w) fh.close()这段脚本的核心是block_bytes参数。64MB 是经验值小于这个值对象数量还是太多聚合不彻底大于这个值上传时并发度不够单对象失败重传成本也高。如果网络是 RoCE 或 InfiniBand可以放到 128MB如果是千兆网32MB 更稳。另一个要注意的点是用tar而不是tar.gz压缩在高性能计算场景里是负优化CPU 开销大而且压缩后的数据没法直接做范围读。聚合之后还要配套一个索引文件记录每个原始文件在哪个 tar 段、偏移量多少、多大。没有索引读取时得解整个包等于白干。索引本身也写成对象放在同一桶里读取时先拉索引再定位数据段两次请求解决。3.3 服务端方案延迟合并、预取与范围读客户端聚合解决了归档场景的问题但没法解决实时写入的场景。任务边写边读文件还没落盘就要可见这时候靠的是服务端的延迟合并策略。网关或者存储节点先接收小对象写入在内存缓冲里攒几百毫秒攒够了再一并落盘类似日志系统的 group commit。延迟合并的关键是攒多久。攒太短合并效果出不来攒太长写完后读不到数据任务以为写完了其实还在缓冲里。我一般建议攒 200ms 到 500ms并配合写入确认机制缓冲落盘成功后才返回写成功让客户端感知不到延迟。这个妥协换来的收益很可观小对象写入吞吐能提升一个数量级。读取侧的辅助招式是预取。HPC 任务的 IO 模式有很强的规律性读文件 A 之后大概率读文件 B因为数据集在目录里按序号排。存储服务端可以在读到某个范围时把相邻范围的数据一起从磁盘拉进缓存。小对象场景下预取命中率做到 70% 以上随机读的时延能降到跟顺序读差不多。预取窗口按数据集特征调图像数据集窗口调大日志分析场景窗口调小。3.4 大文件的写入路径分段与并发HPC 不只是小文件也有几 GB 甚至几十 GB 的单个结果文件。大文件走单对象写入有两个问题一是单连接写不满带宽二是写一半断了全重来。分段上传是标准答案把大对象切成固定大小的段各段并发上传全部完成后再合并元数据。段大小和并发的匹配有个简单公式目标带宽除以单连接带宽就是需要的并发段数。万兆网下单连接大概能跑 500MB/s要跑满 10Gbps 至少需要 20 个并发段。段大小设 64MB一个 1GB 的文件切 16 段并发 16 上传既不会太多段导致元数据压力大也够吃满带宽。上传完成后要做完整性校验分段上传的校验和要落在对象属性里不然数据腐化时根本定位不到是哪一段出的问题。4. 高并发下的隔离与分层多租户服务质量的三个抓手4.1 多租户限流HPC 集群里抢带宽是常态不设限就会死锁HPC 集群通常是多部门共用气象组在跑归档AI 组在训模型材料组在导数据。谁都能往存储里灌数据但不隔离的话一个任务的突发 IO 能把全集群的带宽吃光其他任务全部时延飙升。多租户限流是面向高性能计算的分布式对象存储系统的必选项。限流要在桶级别做配令牌桶算法按部门或项目建桶每个桶给独立的读写带宽配额。配额设多少不是拍脑袋定的要看业务峰值AI 训练读数据集要求稳定带宽给足归档任务是后台跑给低配额保证不饿死别人。限流的粒度要能同时控制带宽和 IOPS两个维度缺一个都会出幺蛾子。只限带宽不限额 IOPS小对象洪水还是能把元数据集群打满。落地时还要注意限流是在网关层做还是存储层做。网关层做实现简单但网关是分布式的每个网关的令牌桶要协调否则多网关加起来会超配。存储层做更精确但改动深。我一般建议先在最前端的接入层做粗粒度限流压测验证效果后再决定要不要下沉。4.2 数据分层与生命周期把 SSD 留给热数据HDD 留给不动的老数据HPC 数据有天然的热温冷属性。训练数据集正在跑是热数据跑完了两周内可能还要复现是温数据归档到国家网格库的项目三年不会碰一次是冷数据。一套集群全用高性能盘贵得没必要全用大容量盘热数据性能又上不去。分层存储把数据按生命周期放在不同介质上策略要自动跑不能靠人工搬。生命周期策略的两个参数是年龄和访问频率。我常用的配置SSD 层承接 7 天内有写入的数据HDD 层承接读多写少的数据归档层留给 90 天未访问的数据。策略落地时有个坑对象迁移期间客户端从哪个层读设计上要让网关做重定向读请求打到对象时如果对象正在迁移等迁移完成再返回数据不能让客户端感知到迁移过程。冷数据迁移到归档介质后读时延会从毫秒级变成秒级。业务侧必须提前知道这个变化不能拿归档数据当热数据处理。我习惯在对象属性里标一个数据层标记客户端 SDK 根据这个标记决定是否走缓存避免每次读冷数据都在等硬盘起转。4.3 网络拓扑感知计算和存储之间的路不能只靠交换机硬撑HPC 的网络和普通数据中心的网络不一样计算节点之间走 RDMA 是常态存储访问也能享受这个红利。分布式对象存储系统如果支持 RDMA 传输时延能降一个量级CPU 开销也大幅下降。但落地时要考虑网卡和交换机的兼容性RoCE 需要无损网络配置流控和 PFC 参数不对丢包重传反而比 TCP 还慢。网络拓扑感知是另一层优化。存储系统的数据分布如果能感知网络拓扑把数据块放在离计算节点近的存储节点上读延时能少吃一跳。做法是给节点打标签标记机架和交换机层级数据分布算法按标签做故障域隔离这条路径做早了收益大做晚了改起来伤筋动骨。建议第一版就实现拓扑感知别等数据写完再迁移。带宽估算也要放在网络设计里。一个常见的公式存储集群总带宽按 5% 的计算节点峰值 IO 来算因为不可能所有节点同时跑满 IO。但如果 HPC 平台的任务调度器不做 IO 感知突发峰值可能几分钟内把所有节点的 IO 都撞在一起5% 就不够了。要么网络留余量要么调度器配合做 IO 整形后者比前者省钱。5. 部署调优避坑性能翻车最常见的 5 个现象5.1 现象小对象读取只有几百 KB/s磁盘利用率不到 10%这是最典型的开局翻车现场。现象是按 4KB 粒度读一万个小对象聚合吞吐只有几百 KB/s但磁盘队列深度很低CPU 也闲得很看起来什么都没干就是慢。原因是 EC 条带读放大。对象虽然只有 4KB但它打在 EC 条带上读一条数据块要同时读同一带内的其他数据块做解码还原。条带宽度是 8 的话一次 4KB 读实际从磁盘捞了 8 个条带块再乘上 EC 的校验块实际 IO 放大了十倍以上。解决方法是前面说的分层热数据小对象放副本池别进 EC 池。如果一定要用 EC就要求客户端侧做聚合把读取粒度提到条带大小以上至少把一个条带的数据一次性读走。我在压测环境里验证过同样一批 4KB 对象从 EC 池挪到副本池P99 时延从 80ms 掉到 2ms不用改任何客户端代码。5.2 现象并发一高写入时延从 5ms 抖动到 500ms还伴随节点心跳超时写入时延抖动的第一个排查对象是磁盘的 WAL。对象存储的每次写入都要先落日志再更新数据文件。如果 WAL 和数据文件在同一块盘上日志的写和数据的写互相抢队列时延就上去了。全闪存集群里这个现象不算严重但混闪或者 HDD 为主的集群里这是头号杀手。另一个隐藏原因是用 HDD 做元数据盘头一跳就把时延打出 100ms。解决办法是同机部署时物理隔离WAL 单独一块 NVMe元数据索引单独一块 NVMe数据盘走 HDD 大容量盘。多花两块 NVMe 的钱换回来的集群稳定性值得。做完隔离后再看时延曲线理论上应该是平的如果还是抖动拿iostat看每个盘的服务时间揪出最慢的那一块。5.3 现象list 桶内对象越来越慢从 1 秒到 10 秒最后直接超时桶里对象数量过了千万级list 操作开始断崖式下降。原因是元数据索引没做分区或者说分区键设计不合理。对象存储的元数据索引一般是按桶维度做的桶里的对象多了一次列表请求要扫的索引条目就多。解决的常规手段是两层第一桶内加前缀分区把对象键的前缀做成时间戳或任务 ID索引按前缀拆成多个分片并行扫描第二如果业务对 list 的实时性要求不高可以做 list 结果缓存用异步刷新代替每次实时查。但缓存可能让客户端看到旧数据对写入后立刻 list 的应用要慎用。我踩过的坑是把任务 ID 放在键的尾部而不是前缀导致所有对象平均散落在所有分片上list 还得全量扫描白做分区后来花了一个下午把历史数据重新刷了一遍前缀。5.4 现象客户端并发从 64 调到 256吞吐没有翻倍反而跌了一半很多人以为并发越多越好在对象存储面前不成立。每个连接都有 TCP 缓冲区占用、CPU 上下文切换、网卡队列排队并发翻四倍单请求时延翻八倍吞吐曲线是倒 U 型。原因在客户端侧的 TCP 参数或者网关的线程池设置。解决方法是分层定位先看客户端所在节点的 CPU 软中断占用再看网关的连接数和请求队列深度最后看存储节点的 QPS。用排除法找到最簿的一层而不是盲目堆并发。我习惯先用脚本扫一个并发梯度比如 16、32、64、128、256每档跑五分钟把吞吐和 P99 时延画出来最高点就是这台客户端的最佳并发数。这个值会随网络带宽和存储集群规模变化集群扩容后要重测。5.5 现象数据迁移或者本地缓存回刷后校验失败文件读出来是坏的数据完整性出问题最难查的场景是多重校验机制之间打架。比如客户端上传时按段计算了 MD5服务端保存的是全对象的 CRC回读时两边对不上。根因通常有两个一是分段上传合并时元数据记录的段偏移量算错了一位二是网关层做过数据重写或转换比如压缩、去重原始校验和失效。解决方法是把校验机制统一成一套从客户端生成校验和到服务端持久化再到回读时校验全链路用同一种算法不许各层各做各的。我一般用 xxhash 跑全链一致性校验速度比 MD5 快一个数量级还能承受高并发。数据迁移后做一轮全量校验是必须的别嫌慢万一漏了坏块后面训练跑到一半出 NaN 才叫真的酸爽。6. 验收基线把性能钉在纸面上的三个基准验证一套对象存储系统能不能用最忌讳拿一条put命令跑完就说挺快。我习惯按下面三步建立基线每一步都留档之后调任何参数都用它对照。第一步是顺序写基准。用大对象分段并发写测聚合带宽和 P99 时延。这个基准验证集群的条带、EC、网络拓扑配置是否吃满了硬件能力。第二步是小对象随机读基准。按生产环境的对象大小分布生成数据集测 IOPS 和时延这一步最接近真实负载也最容易暴露网关和元数据的瓶颈。第三步是混合读写基准。模拟归档和训练同时跑的流量模型验证多租户限流是否生效验证分层存储策略在压力下会不会抖。每次跑完记录五项指标吞吐、IOPS、P99 时延、CPU 占用、网络带宽五个数据放在一起看哪个先到瓶颈一目了然。这五年来我养成的习惯是任何调优动作都先跑一遍基线再动手改完再跑一遍对比绝不凭感觉说好像变快了。性能问题最怕黑匣子把基线钉在纸面上翻车了才知道往哪个方向查。这套方法也可以用在验收厂商方案上把基线测试结果作为入场条件能省掉后面大把扯皮的功夫。希望帮到你。本文还有配套的精品资源点击获取
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑