大数据架构中的存储设计:HDFS、S3、对象存储如何选择?
最近做存储选型评审的时候,业务方又抛来一个经典问题:我这一堆数据,每天好几个TB,既要跑离线批处理,又要供实时的即席查询,历史数据还要留两三年,到底应该放HDFS还是S3还是各类对象存储?
这个问题我入职这几年前前后后被问了不下十次。每次聊起来,大家第一反应都是拿“HDFS是文件系统,S3是对象存储”这种教科书定义来开头,但真到架构设计的时候,光说这个完全不够。今天干脆把我在存储选型上的一些判断方法、踩过的坑和实际落地经验整理出来。这篇文章不打算给你一个标准答案,因为本来就不存在放之四海而皆准的标准答案,但我可以给你一套拆解问题的维度,以及几个能直接参考的混合架构方案。
适合谁看?如果你的数仓、数据湖、实时管道正在做存储层选型,或者你已经在用HDFS但被NameNode、磁盘扩容、小文件问题折磨得不行,再或者你公司正在上云、想把本地大数据体系迁到对象存储上,那这篇文章应该能给你不少启发。
1. 三种存储的真实身份:别被“分布式存储”这个标签骗了
很多人在选型的时候犯的第一个错误,就是觉得HDFS、S3、对象存储都是“给我一个大空间,我往里放文件”的东西,好像只是接口不一样。这是最大的误解——它们的架构内核、数据访问模型、计算引擎对它们的依赖方式完全不同。
1.1 HDFS是“为你量身定做大数据计算”的文件系统
先说HDFS。它的设计目标从一开始就不是给人用的,而是给MapReduce这种批处理框架用的。所以它的核心设计全部围绕“大文件、顺序读、粗粒度写”来展开。
HDFS默认把文件切成128MB甚至256MB的块,每个块在每个机架上有副本(默认三副本),NameNode管理所有元数据。这种设计带来三个结果:
第一,计算可以靠近数据。Spark的Task可以调度到存有对应数据块的节点上,从本地磁盘读数据比走网络快得不是一个量级,这是HDFS在大数据生态里最大的护城河。
第二,它天然不适合小文件和海量随机读。每个文件、每个目录都要在NameNode内存里占一条记录,一个小文件大概消耗几百字节内存,千万级小文件直接能把NameNode的堆内存撑爆。它适合的是“少而大”的文件,不是“多而碎”的对象。
第三,写模式是“一次写入、多次读取,不允许修改”。虽然HDFS后来支持append和truncate,但它的设计哲学依然是流式写入。你没办法在中间插一段数据,也没法对单个字节做随机写。这套约束在MapReduce和离线数仓场景是优势,因为不需要那些复杂文件编辑能力;但到了实时计算、在线服务场景就非常难受。
1.2 S3和对象存储是“无限寄存柜”,不是文件柜
S3背后的产品理念是完全不同的。它本质上是一个KV存储,key是对象名(比如logs/2025/03/27/app.log),value是对象内容。虽然你看起来是在“按路径访问文件”,但它没有真实目录层级,logs/2025/03/27/只是一串key前缀而已。
这带来什么差别?
对象存储允许你存任意大小的对象(单对象最大可以到5TB级别),容量近乎无限扩展,不需要像HDFS那样规划节点数、操心磁盘满了怎么办。它通过HTTP REST API访问,任何一个语言任何一个客户端都能读写。跨区域冗余、版本管理、生命周期策略这些能力是内置的,存文件的同时也顺便把容灾备份做了。
但它也有致命约束:不支持POSIX语义的随机写、追加写和Rename。追加一个字节,在对象存储里的实际成本是“把整个文件读出来、合并新内容、再整对象写回去”。如果你想做每秒几百次更新同一个对象的操作,对象存储基本做不了。
我经常用一个类比来描述这两个东西的差别:
HDFS像一个你办公室里的专用文件柜,你做报表用的资料都堆在里面,抽屉上有专门的索引,办公室的人来来去去都熟悉它的摆放规则,拿取很快,但你得自己维护这个柜子,还得定期处理塞得太满的问题。
S3更像一个城市级的公共储物仓。你只要往仓里扔任何东西,仓都会给你一个收据号码,你凭号码随时取件。储物仓几乎不会满,也几乎不会丢东西。但它不帮你把东西整理成“编号连续的本子”,你要追加内容就必须把整件东西重新打包扔进去。
1.3 其实你已经用了不止S3一家:OSS、COS、OBS、GCS
聊到对象存储,很多团队第一时间会提S3,因为AWS生态太强势。但在国内私有化和混合云环境里,阿里云OSS、腾讯云COS、华为云OBS、MinIO自建集群同样是非常主流的选项。它们在核心能力上对齐S3,但细节差异不少。
从选型角度,我更建议把“S3”这个词当成“对象存储兼容协议”的代名词来理解,而不是特指AWS那一朵云。你真正要判断的是:我的计算引擎能不能通过S3A协议访问这个对象存储?权限体系怎么打通?吞吐和延迟指标够不够? 只要协议兼容,迁移成本就低很多。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 为什么现在的架构里,HDFS、S3和对象存储会同时出现
矛盾点来了:HDFS有数据本地性优势,对象存储有弹性和廉价优势,那是不是选一个就行?实际上,我见过的大多数成熟团队,甚至很多月活几亿的业务,存储层都是“HDFS + 对象存储”双轨制。原因要从两条线来理解。
2.1 自建Hadoop时代的“家底”都挂在HDFS上
过去十年,凡是自建大数据平台的团队,绝大多数以HDFS为底座。Hive数仓的/user/hive/warehouse、Spark作业日志、Flume采集数据、HBase的WAL和HFile、Kafka备份数据,全部长在HDFS上。这些数据本身是“文件目录”语义的,要迁移到对象存储不是改一个路径那么简单——你需要考虑Hive表的分区发现、文件格式兼容、权限模型、压缩方式、小文件合并策略,这一整套都得跟着变。
我见过不少团队尝试一次性把Hive全量表迁到S3,结果在OLAP查询性能上掉了一个量级,又灰溜溜迁回来。不是说S3不能跑Hive,而是Hive的FileInputFormat对对象存储的适配、任务并发度、列式文件读取路径都需要重新调优,不是复制粘贴能搞定的。
所以大量公司采取的策略是:HDFS继续承载老数仓和热数据的批处理,对象存储承载新增的日志归档、数据湖底座和冷数据生命周期管理。两者之间用定时同步或实时管道打通。这种“既得让老马继续拉车,又得让新车跑起来”的过渡状态,是现阶段大数据架构里最常见的样子。
2.2 云原生化之后,计算和存储必须拆家
另一个推动力是计算存储分离思想成为主流。传统Hadoop集群的问题在于:计算和存储耦合在一起,扩容存储必须连带扩容计算,只加磁盘不加CPU是件很尴尬的事。而云上Spark、Flink作业是弹性的,跑完就要释放资源,数据如果还落在HDFS上,你就得保留一整套常驻HDFS集群,成本高得离谱。
于是大家把数据集中放进对象存储,计算集群起一个跑一个,跑完释放。数据不动,计算资源随用随开,这才是云上大数据的正确姿势。S3/OSS在这里扮演的就是“计算与存储之间的解耦层”。
当然,纯S3跑Spark还有一个众所周知的短板:数据本地性没了。Spark作业从本地HDFS读数据可能5分钟跑完,改成从S3读可能要15分钟——因为数据要先经过网络从远端存储传到计算节点,IO带宽就是瓶颈。为了解决这个问题,各家引擎都引入了缓存层,比如Spark的spark.sql.parquet.cacheMetadata、Alluxio本地缓存、或者EMR的S3缓存模式。也就是说,对象存储负责“存”,本地盘/缓存负责“热”,两者不是二选一,而是搭配使用。
2.3 湖格式的出现,让对象存储补齐了HDFS的表管理能力
早些年对象存储在大数据场景找不到位置,有一个重要原因:它没有“目录/表”语义。HDFS天然可以用/warehouse/table_name/partition_date=xxx/这种目录结构来组织一张Hive表,Spark/Hive扫描分区的时候,只要列目录就能发现所有数据分片。而S3没有真正目录,列目录的性能和一致性都不可控。
这个痛点被湖格式解决掉了。
Apache Iceberg、Delta Lake、Hudi这三大湖格式引入了一个关键机制:表元数据独立于文件系统。表的分区信息、文件清单、快照版本全部记录在元数据文件里,查询引擎不再依赖“列目录”去发现文件,而是读取一个manifest清单,直接精确拿到需要读的文件列表。这让“S3 + Iceberg”的组合在功能上完全具备了替代“HDFS + Hive分区目录”的能力,而且事务性、时间旅行、Schema演进能力还更强。
一句话总结:湖格式把原来HDFS负责的“文件目录组织”职责接管走了,对象存储只负责当一个可靠的大容量存储底座。至此,HDFS在大数据架构里最硬的存在理由被消解了一大半。
3. 选型判断框架:从六个维度做决定,而不是拍脑袋
现在来回答标题里那个问题:到底怎么选?我的经验是,不要先问“哪个好”,先问“我的场景里,哪些约束是不可妥协的”。下面这六个维度我每次选型都会过一遍。
3.1 访问模式:顺序大读还是随机小读?
HDFS适合的顺序读场景、批处理场景、全表扫描场景,如果任务的数据量在几十个GB的量级、且对运行时间敏感,那HDFS依然是利器。对象存储的延迟天然比本地盘高几十倍,即使缓存命中率高了,小文件的随机读取性能也追不上本地数据。
反过来,如果数据需要被多个业务系统频繁下载、跨地域共享、通过REST API让不同语言读写,那对象存储就是唯一合理选择。HDFS的RPC接口不是RESTful的,跨网络访问要搭好多层代理,开发成本极高。
我自己的判断标准大概是这样:
| 访问模式 | 推荐存储 | 理由 |
|---|---|---|
| 大批量顺序读(跑离线批处理) | HDFS或本地缓存层 | 数据本地性,吞吐高,延迟低 |
| 海量数据冷存储,偶尔读取 | 对象存储 | 成本低,容量无限,生命周期管理 |
| 小文件频繁读取 | 对象存储 + 缓存加速,或本地盘 | 对象存储对小文件IO不友好,必须有缓存 |
| 数据跨越多个数据源/多语言访问 | 对象存储 | REST API统一访问,生态广 |
| 需要随机写入更新 | 都不合适(用数据库/消息队列) | HDFS和对象存储都不支持高效随机写 |
3.2 时效性:数据要多久才能被读到?
如果你的管道是“日志产生后10秒内就要入仓,供实时看板查询”,那这个数据不进HDFS也不进对象存储,而是先进Kafka + Flink兜一圈,最后落到OLAP引擎(ClickHouse、Doris等),再异步归档到对象存储。
如果时效是小时级或天级,离线批处理用HDFS或者对象存储都可以,主要看你的计算集群是不是常驻。常驻集群用HDFS;弹性集群用S3。
有一点很关键:不要让存储选型去迁就时效性。当你发现“我们的报表要求秒级,所以数据必须落HDFS”的时候,大概率是架构已经出问题了——秒级查询的能力应该由OLAP引擎负责,HDFS和对象存储只是它的数据源而已。
3.3 数据量和增长趋势:容忍NameNode还是容忍API费用?
数据和规模直接决定运维复杂度。
HDFS集群到PB级之后,NameNode的元数据内存、磁盘坏盘率、机架网络规划、集群均衡都会成为日常麻烦。你会开始思考联邦、ViewFS、甚至用第三方元数据服务,这些复杂度不是每个团队都愿意扛的。我见过一个中等规模团队,维护60节点HDFS集群,光磁盘故障和NameNode告警每周就得花半天处理。
对象存储则把这些事全外包了。你不需要准备磁盘,不需要做多副本,不需要管机架,只需要给钱。但对象存储的钱不是单向的——PUT、GET、List请求每一个都要计费,特别是“按量读取”的场景,如果业务周期性全量扫描数据,请求费用可能比存储费还贵。
所以选型要算总账:
- 小规模(几十TB到几百TB),团队有运维能力,批处理为主:HDFS更划算
- 大规模(PB以上),需要按需弹性,缺少专业运维:对象存储综合成本更低
- 数据很少但访问极频繁(比如图片、小文件):对象存储配合CDN/CDN回源,而不是HDFS
3.4 成本模型:隐藏的“计算时间”远比存储单价重要
很多团队选型只比“每TB多少钱”,忽略了一个更重要的项:计算引擎读数据的时间成本。存储便宜10%,但每次Spark作业读数据多花30%的时间,一年下来多烧掉的CPU费用可能远超存储差价。
拿一个真实场景举例。一个日志分析任务每天处理2TB数据,数据放HDFS计算耗时40分钟;放S3第一次跑耗时70分钟(无缓存),加了Alluxio缓存后再跑耗时15分钟。表面上看S3存储单价便宜,但你要为Spark任务多付的CPU时间埋单。唯一划算的方式是数据访问有较高重复率,缓存能持续命中,或者任务的实时性要求不高,多跑一会儿没人在乎。
我建议做选型对比时,至少要把下面这三项放进成本表里:
存储费用:每TB每月价格(含冗余策略/跨区域复制费用)
请求费用:数据生成和消费频率对应的PUT/GET费用估算
计算时间差:预估读HDFS和读对象存储的任务耗时差异,折算成计算资源费用
3.5 容灾与合规:跨地域复制难度
HDFS的容灾主要靠副本和快照。副本防机器坏盘,快照防误删。但跨机房容灾要HDFS Federation加定时DistCp同步到异地集群,复杂度很高,RPO(恢复点目标)能到小时级就算不错了。
对象存储的容灾几乎是开箱即用。S3跨区域复制(CRR)、OSS跨区域复制、版本控制、生命周期规则,配置好之后数据自动同步到异地。对于银行、金融这些有合规要求的场景,对象存储的审计能力、加密能力(SSE-KMS)、访问日志都远超自建HDFS。
如果你所在的行业有“核心数据必须异地备份”的合规要求,那对象存储基本是必选项,HDFS只能当主存储,备份层必须挂一个对象存储。
3.6 团队能力:你养得起HDFS的“专属运维”吗?
这是最容易被忽略也最现实的问题。HDFS不是装上就能跑的——你需要有人懂NameNode内存调优,懂DataNode磁盘故障替换,懂机架感知配置,懂Balancer怎么跑,懂小文件怎么治理。如果团队里只有两三个开发,没人专职维护大数据集群,那自建HDFS就是在给自己挖坑。
对象存储的运维负担约等于零。你的团队只需要会配置权限、管理桶策略、设计key的命名规范,剩下的交给云厂商。如果选MinIO自建对象存储,也比HDFS简单得多——因为它不需要NameNode这种单点组件,架构更轻。
4. 混合存储实战:一套我亲测过的大数据存储参考架构
理论说了一堆,给一个可落地的混合存储设计。这个架构我在多个项目的实际数据管道里跑过,不是理想化设计,是踩过坑调整过的。
4.1 分层设计:热、温、冷三类数据各就各位
整个存储体系按数据温度分三层:
热层(秒级~小时级):实时计算和近期批处理需要频繁访问的数据,放在HDFS或计算节点的本地NVMe缓存里。这里还包含Kafka本身(Kafka用本地磁盘,不用HDFS也不宜用S3)。这一层的体量一般控制在一周到一个月的数据量。
温层(天级~月级):需要每日或每周汇总访问的数据,放在对象存储。数据通过实时管道或定时任务从热层同步过来,分区组织形式采用湖格式管理(Iceberg或Hudi)。Spark、Flink、Presto都能直接查询这层数据。
冷层(月级以上):只做归档,很少访问。依然放对象存储,但启用低频访问/归档存储类型,配合生命周期策略,比如90天后自动转为归档,180天后自动删除或转移到冷归档。这层成本可以压到最低。
这种分层的好处是:热层的读写延迟能满足实时和近实时需求,温冷层的存储成本很低,数据不需要搬迁,只是通过生命周期规则自动降冷。整个体系里HDFS只负责热层和计算缓存,对象存储负责温冷层和数据交换中心。
4.2 一个真实的数据链路:日志管道 + 离线数仓 + 即席查询
我参与过的一个系统,每天处理约5TB日志数据,核心链路是这样的:
- 日志采集写Kafka。
- Flink消费Kafka,做实时ETL,然后双写:一份写ClickHouse供实时看板,一份写对象存储(按天分区,格式Parquet,用Hudi管理)供离线分析。
- 离线数仓的DWD层保留在HDFS上,因为每天凌晨有大批量关联计算,HDFS的顺序读性能让任务稳定在2小时内跑完。等计算完成,结果表自动同步到对象存储,供Presto做即席查询。
- 历史明细数据超过3个月后,从HDFS清理掉,只保留对象存储里的副本。
这个设计里,HDFS的任务非常纯粹——它只是每天凌晨批计算的“高速暂存区”,数据计算完就归档到S3,不承担长期存储职责。对象存储才是数据仓库真正的底座。
你可能会问,为什么不用HDFS直接做长期存储?因为公司数据要保留三年,一年就是1.8PB,三年5.4PB,HDFS集群要扩到几十个节点,还得处理三次副本带来的磁盘成本。丢S3冷归档,成本能乘以一个很小的系数。这个账目算完,决策就非常清晰了。
4.3 HDFS到对象存储的迁移路径:不要“大爆炸”,要“绞杀式”
如果你的现状是HDFS已经承担了数仓所有数据,想逐步迁移到对象存储,我的建议是不要搞一次性全量迁移。所谓“绞杀式迁移”是更稳妥的路径:把新数据先写到对象存储,老数据按热度逐步回填,等对象存储上的数据验证没问题后再切读。
具体步骤上,这几点值得注意:
- 用分布式拷贝工具迁移历史数据(如DistCp配置S3A协议),带宽要限速,避免影响线上任务。
- 文件校验环节必须做。对象存储和HDFS的checksum算法不完全一致,迁移后要跑一遍
hdfs dfs -checksum和对象存储的ETag对比,或者直接用Hive的ANALYZE TABLE ... COMPUTE STATISTICS验证元数据。 - 分区粒度迁移,比如先迁三个月前的冷分区,再迁上个月分区,最后迁当月分区。每次迁移完,跑一遍典型查询对拍性能和结果。
- 双跑期保留两个月以上。很多bug只有在真实负载下才会暴露,别急着停HDFS集群,至少确认连续两个月报表口径一致再下线。
5. 实测中最容易踩的坑:HDFS和对象存储各自的“隐藏代价”
光说选型框架还不行。下面这些坑我是实打实踩过的,罗列出来希望对你有帮助。有些问题看文档根本发现不了,非得到线上跑一段时间才知道。
5.1 S3A文件系统的“写后读”坑:别在同一个并发任务里边写边读
很早之前我有一段Spark Streaming代码,把聚合结果写到S3后立刻读同一路径做后续处理。当时Amazon S3已经是强一致的了,代码在AWS上跑得好好的,但切到阿里云OSS后偶发报“File Not Found”。
查了很久发现,问题出在OSS兼容层的“写后读”语义。虽然官方文档说支持强一致,但在高频并发写同一个目录、且马上读的场景下,还是可能出现短暂不可见。解决方法是写完成后强制做一次List操作或添加wait机制,更稳妥的是不依赖“边写边读”,让下游直接从元数据系统获取文件清单,而不是扫目录。
5.2 小文件问题:对象存储的List操作和PUT费用会被刷爆
HDFS有小文件问题,对象存储也有,但表现完全不同。HDFS的小文件问题是占满NameNode内存,对象存储的小文件问题是三个方面:List请求过多、PUT请求费用过高、计算引擎读取时任务调度开销大。
举个例子,一个Flume任务每5秒写一个文件到S3,一天就是17280个对象,一个月50万个。存储费用也许不高,但归档和清理这些对象时,List+Delete的请求费用会超出预期。更麻烦的是,如果有批处理任务要读取这些文件,Spark需要一个个FileStatus,光列出文件都要好几分钟。
治理手段无非几种:
- 写之前做缓冲,积攒几分钟或几十MB再落盘
- 用Hudi/Iceberg的Clustering/Compaction能力定期合并小文件
- 消耗型数据(比如原始日志)设为生命周期自动清理,不长期保留
5.3 HDFS扩展性:扩容不是加节点就完事
HDFS扩容看起来很简单:加几台DataNode,执行hdfs balancer把数据均衡一下就完了。但等到你集群大了,会遇到几个隐形问题:
- NameNode堆内存:文件数超过千万后,GC时间会明显变长,需要升级堆内存或者做NameNode Federation,这都不是一两天能搞完的事。
- 机架感知:如果没配置机架感知,HDFS默认把所有节点当成一个机架,副本策略会失效,容易出现数据分布不均。配置机架感知的脚本和拓扑需要网络团队配合。
- Balancer带宽:集群数据不均衡时跑Balancer,默认带宽只有1MB/s,几TB的数据均衡可能要跑好几天。可以把
dfs.datanode.balance.bandwidthPerSec调大,但要小心影响线上任务。
如果你只是“临时缺容量”,加节点很爽;但如果你的增长趋势是持续性的,我更推荐考虑把冷数据往对象存储转移,而不是无脑扩HDFS。
5.4 服务端加密和权限模型:不要等审计才发现不能对齐
HDFS的权限模型基于POSIX的user/group/other,靠Kerberos做身份认证。对象存储的权限模型是Bucket Policy + IAM策略,基于资源ARN和Principal。两者对齐起来没那么容易。
有次一个客户要求“所有写上传的数据必须加密”,HDFS上我们启用了透明加密(Transparent Encryption)加KMS,一切正常。但迁到S3的时候,发现S3的SSE-KMS加密默认只对新建对象生效,存量对象需要做一次数据复制才能“加密落盘”。如果没提前规划,审计时发现“老数据没加密”就很被动。
所以建议:在上云/迁移第一天就把加密、权限、审计三件套对齐。宁可慢一周,也不要后期返工。
5.5 网络带宽的账:本地HDFS和云上对象存储之间的“隐形墙”
自建机房IDC里部署HDFS,云上部署对象存储,中间的网络链路会成为一个隐藏瓶颈。数据从IDC传到云对象存储,走公网上行带宽,既慢又贵,而且有断点续传、超时重试这些问题。即使走专线,也有带宽费用。
很多团队会在IDC内部临时搭一个MinIO,本地先落地数据,再由MinIO异步复制到云端对象存储,这样至少断网时采集链路不会直接挂掉。这也算一种比较常见的中间态方案。在设计存储架构时,一定不要把“跨网络读写数据”当成常态路径,否则你会时不时撞上超时、限流和瞬时不可用。
6. 给选型人一把“尺子”:五条可以直接用的判断规则
纯聊框架容易虚,最后给几条我在内部评审时反复用的判断规则。这些规则不一定适用于所有场景,但它们能把模糊争执变成可执行的选择。
-
规则一:如果数据是给“大数据计算引擎”当饭吃,且计算集群是常驻的,用HDFS;如果计算集群是弹性启动的,用对象存储。
常驻集群用HDFS能吃到数据本地性红利,弹性集群用HDFS只会拖累集群启动速度和解耦灵活性。 -
规则二:如果数据生命周期超过一年,且不是每天都要全量扫描,直接进对象存储冷/温层。
长期保存是对象存储的绝对优势区,HDFS保存一年以上的数据成本劣势会越来越明显。 -
规则三:如果业务方提出“我想像操作本地文件系统一样操作它”,选HDFS或NAS,别选对象存储。
追加写、Rename、随机读这类需求,对象存储确实做不到,强行做只会开发出一堆绕来绕去的兼容层。 -
规则四:如果访问是“通过公网或跨云跨地域”的,选对象存储。
HDFS的RPC基本不适合跨地域访问,你最终会在前面套一层WebHDFS或者对象存储网关,那不如直接用对象存储。 -
规则五:如果团队没人愿意背“NameNode出问题找我”这个锅,别自建HDFS。
这不是技术问题,是运维能力问题。做选型的时候,这个因素的决定权可能比所有技术指标都大。
7. 最后说几句实际感受
做了这些年存储方案,我的一个体会是:存储选型本质上是在选“这套架构的运维复杂度和弹性能力的平衡点”。HDFS给你的是确定性——性能可预期、数据本地性可控,代价是运维压力。对象存储给你的是自由度——容量弹性、生态丰富,代价是把性能和一致性的掌控权交给了外部服务。
如果你的团队还年轻,没有专职大数据运维,我更倾向建议“对象存储优先,必要时引入湖格式”的路线。这样你能把精力花在数据处理本身,而不是老集群的那些琐碎事情上。如果你的团队有成熟的Hadoop运维经验,而且现有HDFS集群已经跑得很稳,那冒然做“HDFS换S3”的决策也不划算——性能可能打折扣,迁移又要提心吊胆好几个月,最好的选择反而是混合架构,让两者各管一段。
我个人在实际项目中最喜欢的一句判断就是:没有最好的存储,只有最匹配当前约束的组合。 先把约束条件列清楚,选型就变成一道排除题了。希望这篇文章能给你一些可参考的排除思路。
