
1. 存算分离到底拆的是什么先把这个概念讲清楚大数据圈子里这两年有一个词被反复提起存算分离。说它是老技术吧确实十多年前就有分布式存储和计算分开的思路说它是新技术吧近几年云厂商、开源社区又全都在重提。我做数据平台相关工作这些年最大的感受是很多人对存算分离的理解停留在存储和计算分开放这个字面意思上但真到了选型、排障、设计架构的时候又容易踩坑。这篇文章我就把大数据领域里存算分离的典型应用场景、底层逻辑、落地细节、常见问题一次讲透。先说清楚它到底拆的是什么。传统的大数据架构尤其是Hadoop生态早期那套计算节点和存储节点是绑在一起的。每个DataNode既负责存数据块也负责跑计算任务。数据本地性Data Locality是这种架构的核心优势任务调度器会尽量把计算调度到数据所在的那台机器上避免数据跨网络传输。但问题也随之而来存储扩容和计算扩容被绑死了。你的集群如果是因为存储不够所以要加机器那加的机器同时也带来了计算资源但这些计算资源如果不跑任务就闲置了反过来计算不够用的时候加机器机器自带的磁盘又会带来多余存储。这种耦合在数据量小的时候不觉得数据量一上来成本浪费非常扎眼。存算分离的出发点就是把这两件事拆开数据统一放在独立的存储层可以是对象存储、分布式文件系统也可以是云上的托管存储服务计算层按需拉起用完可以释放。存储层和计算层各自按自己的节奏扩容互不拖累。这个思路听起来简单但真正落地的时候牵涉到非常多的技术细节比如计算引擎怎么感知远端数据、缓存怎么做、元数据访问性能怎么保证、小文件怎么治理等等这些后面我会逐一展开。从我的实际观察来看存算分离这几年被讨论得越来越多还有个很重要的背景是数据湖和AI训练这两类负载的兴起。数据湖要求多个计算引擎Spark、Flink、Presto、Hive等能共享同一份数据如果数据散落在各自集群的本地盘上共享就无从谈起AI训练的场景里样本数据可能上百TB训练集群是GPU机器非常贵不可能让GPU节点同时承担存储职责。两个趋势一叠加存算分离几乎是必然选择。那是不是所有场景都应该存算分离并不是。这就要看下面这张对比表里列出来的几个维度对比维度存算一体架构存算分离架构存储成本需要为计算节点配置大量磁盘成本偏高可使用低成本存储介质按量付费资源利用率存储计算绑定容易互相牵制各自弹性伸缩利用率更高计算弹性扩缩容要连带考虑存储动作笨重计算集群可快速拉起或释放数据共享数据被集群独占多引擎访问困难多计算引擎可共享同一份底层数据网络开销计算尽量本地读网络压力小每次读取可能跨网络对带宽压力大运维复杂度要同时运维存储和计算机器规模大存储统一托管计算集群轻量化这个表格是评估架构选择时的参考框架但不是万能答案。比如你的业务如果以超高并发点查为主、每次查询都是毫秒级返回那存算分离的反向网络开销和元数据瓶颈可能会让你很难受但如果是分析型负载、海量历史数据、周期性跑批那存算分离的收益就会非常明显。2. 哪些业务场景最适合用存算分离场景这件事不能泛泛而谈我说几个自己接触过、也看到行业里反复验证过的典型方向每个方向都对应不同的技术组合和注意事项。2.1 离线分析 / 数据湖场景这是存算分离应用最成熟的场景。数据源如业务库binlog、埋点日志、第三方接口数据经过采集通道统一落到对象存储或分布式文件系统形成原始数据层。下游的Spark批任务、Hive数仓任务、Presto即席查询都通过计算集群直接读取远端存储。我见过一个典型的存量大数据平台改造案例原来一套Hadoop集群跑了两百多个周期任务数据总量大概纯用户行为日志就有几十TB存储水位一直在告警而计算资源在凌晨跑批之外的时间里又大量闲置。后来把历史数据分层低频访问的数据全部迁到对象存储高频访问的热数据暂时留在本地盘计算集群只保留必要规模高峰期弹性扩容。改造完以后存储成本下降了大概四成任务运行时间没有明显劣化因为大部分任务跑的还是近期的热数据冷数据计算频率低多花一点网络开销可以接受。这种场景的技术核心是计算引擎要能原生对接对象存储。现在Spark、Flink、Hive都提供了成熟的连接器配置好Endpoint、桶名、认证信息之后SQL里可以直接读写OSS、S3这类存储的数据。但要注意底层文件格式最好统一用Parquet或ORC这类列式存储格式既能压缩空间也能减少远端扫描的数据量对网络开销是非常友好的。2.2 机器学习训练中的特征与样本共享AI训练场景是存算分离近两年增长最快的领域。训练集群是昂贵的GPU机器正常情况下没有任何人会把训练数据副本直接放在GPU节点的本地盘上那样既浪费GPU的存储空间也很难做数据版本管理。更常见的做法是特征数据和样本集统一放在对象存储训练任务启动时训练框架从远端拉取数据配合缓存和预取机制做数据装载。我之前参与过一个推荐场景的特征平台建设特征数据每天全量快照写入对象存储各个算法团队根据自己的特征需求做投影和抽样然后提交训练任务。不同团队的训练任务跑的模型不一样、数据范围不一样但底层都是同一份特征快照。如果还是传统的存算一体架构每个团队各拉一份数据到自己集群里光是存储冗余和文件拷贝就够头疼了。换成存算分离之后数据只有一份按需读训练任务结束GPU集群就可以释放。这个场景里比较关键的参数是数据读取的吞吐和预取策略。GPU训练任务的数据读取往往是Pipeline式的如果模型每个Epoch都重新从对象存储拉一遍全量数据IO会成为明显瓶颈。实操中一般会加一个分布式缓存层比如Alluxio或者用训练框架自带的缓存机制把高频访问的特征数据缓存在计算节点本地只在样本集有更新时才重新装载。2.3 实时数仓与OLAP分析实时数仓场景下存算分离解决的核心问题是写入和查询的隔离。数据写入侧通常是Flink或Kafka Connect把流式数据落到消息队列或者直接落到存储层查询侧是Doris、ClickHouse、Presto这类OLAP引擎。写入和查询如果共用一套资源很容易出现写入高峰拖垮查询性能的互相干扰。存算分离之后写入侧只负责写存储查询侧只负责算中间通过存储层解耦。现在很多OLAP引擎也推出了自己的存算分离形态底层存储用对象存储计算节点可以秒级扩缩容。我实际测下来这种形态对查询频率波动大的业务特别友好典型的就是数据可视化大屏场景。大屏什么时候看的人多业务汇报的时候、大促期间流量波峰很陡波谷又很闲。如果用传统集群你得按峰值准备资源日常一大半资源白交钱用存算分离波峰时多拉几个计算节点波谷时缩掉账单差别非常大。2.4 海量多媒体与遥感影像类数据这个场景可能很多人不熟悉但它是存算分离价值非常直观的领域。遥感卫星影像、医疗影像、自动驾驶路测数据每一类都是PB级别的非结构化数据而且处理流程通常是数据先落地、算法再跑。存算分离架构下原始影像数据统一存在对象存储里多个团队可以同时启动各自的处理任务比如一个团队做几何校正一个团队做目标检测另一个团队做镶嵌成图大家读的是同一份底图但各算各的互不干扰。这类场景还有一个特点就是突发性计算很强。一次自然灾害应急响应可能需要短时间内把某个区域的影像全量重处理一遍计算量是平时的几十倍。存算一体的集群根本不可能为这种突发场景做储备存算分离配合弹性计算则可以做到平时小集群维持应急时大规模扩展。这种能力背后涉及的并行调度、数据分片读取、任务优先级等技术本质上都是围绕存储与计算解耦来设计的。2.5 多集群隔离与租户共享最后一个高频场景是平台层面的当你的数据平台要服务多个业务线、多个租户的时候存算分离几乎是必须的。每个业务团队都想用自己的计算资源跑任务但底层数据希望能统一管理、统一做权限控制。存算分离之后数据统一在存储层做权限和血缘管理计算层为各团队建独立的虚拟集群按各自的配额弹性伸缩。这里有个容易忽略的点所谓权限控制不能只在计算层做因为有能力的人完全可以绕过计算引擎直接用存储客户端去读数据。所以存储层本身要做细粒度的授权比如对象存储的桶策略、目录级的读写权限、临时凭证机制。很多公司在存算分离改造中踩过权限的坑这里我建议安全设计要前置别等数据都迁上去了再补权限。3. 一份真实的存算分离落地实录从Hadoop迁移到对象存储弹性计算前面讲了很多场景这一节我完整还原一次真实的存算分离改造过程。案例背景是某个中型互联网公司的用户行为分析平台原始架构是一套自建的Hadoop集群上面跑着埋点日志的清洗、数仓ETL、日常报表查询。问题出在数据增长太快HDFS的存储水位常年超过80%DataNode磁盘不够用但加节点又带来CPU和内存冗余。整个集群两百多台机器真正忙的时间段每天只有几个小时其他时间是纯闲置。管理层对成本意见很大。这个案例里的方案不算复杂但每一步都有实际的坑。我按流程拆开讲。3.1 数据分层与迁移策略第一步不是迁移而是盘点。我们把HDFS上的数据按访问频率分了三层热数据最近7天、温数据最近90天、冷数据90天以前。热数据留在本地HDFS保证近实时报表的性能温数据和冷数据迁移到对象存储。这个分层策略很关键如果一刀切全部迁到远端每天的ETL任务读取性能会明显变差业务那边肯定炸。迁移工具当时对比了几种方案最后选择了分布式数据同步工具配合对象存储的批量导入功能。迁移过程中要注意的是保持文件目录结构和分区规则不变比如原始路径是/warehouse/event_log/dt2024-06-01迁移后对象存储里也保持同样的目录层级这样Hive或者Spark的元数据表只需要修改location指向即可不需要改SQL逻辑。这里有一个迁移前必须做的事小文件合并。原来的HDFS集群因为历史原因有大量几十KB到几MB的小文件这些文件如果直接原样搬到对象存储后续查询的性能会很难看。为什么因为对象存储是按请求计费、按对象粒度做元数据管理的访问一个小文件和访问一个1GB大文件request次数是一样的但小文件需要发起的请求数量指数级增长。我们当时用Spark任务对历史分区做了一次重写把小文件按分区合并成128MB左右的Parquet文件再批量上传。这一步耗时了两天但换来了后面查询性能的稳定。3.2 计算引擎对接与缓存设计数据迁到对象存储之后第二步是让计算引擎能够正常读取。Spark任务通过spark.hadoop.fs.oss.impl这类配置指向对应的文件系统实现Hive则要修改hive.metastore.warehouse.dir或者表的location。这里踩过的最大的坑是由于对象存储的list操作比HDFS慢一个数量级Spark在启动阶段如果需要对一个大目录做全量list任务启动时间会从几秒变成几十秒甚至几分钟。解决办法有几个一是尽量用分区裁剪查询条件里带上分区字段让Spark不要扫描全目录二是利用存储的清单manifest机制预先将分区路径清单生成好任务启动时直接读取清单文件三是对高频访问的元数据做缓存比如用Alluxio或者JindoFS的Namespace服务。我们对绝大多数日报任务做了分区裁剪治理之后启动耗时的问题基本不再出现。缓存层面我们当时的策略是按需开启。ODS层的清洗任务每天只跑一次读的是当天的增量数据缓存意义不大但报表团队的即席查询经常反复扫描某些维度表这类任务开缓存收益非常明显。Alluxio的Local Cache可以配置在计算节点本地盘上命中率高的场景下查询响应时间和原来本地读差距很小。3.3 任务调度调整与成本优化存算分离改造不是迁完数据就结束了任务调度层面也要调整。原来的调度策略都假设数据在本地任务启动后直接就近读时间敏感度相对宽松。改到远端读之后本地性这个概念不存在了任务调度器要考虑的是怎么让计算节点和数据之间的网络路径最优。我们当时用了弹性伸缩组白天常规任务跑在固定规模的常驻集群上晚上大任务和补数任务高峰期自动扩容一批临时节点跑完自动释放。这里涉及到一个很实在的成本参数对象存储的请求费用和流量费用。如果任务写得不好频繁list目录、反复读相同的数据请求费用可能比存储费用还高。我们做过一次优化之后把每日的存储访问请求次数降了一个量级主要是做了三件事压缩读取量、增加缓存命中、减少list操作。3.4 踩过的坑与排查实录如果只讲方案不讲坑等于没讲。说几个记忆深刻的第一个坑是认证配置遗漏。对象存储的访问凭证如果只配在了Spark的core-site里而HiveServer2走的是另一套配置那么Hive任务起来后你会看到一堆莫名其妙的PermissionDenied错误。排查了整整一个下午最后发现是HiveServer2的aux jar里没有带上新的存储凭证。这个问题的通用教训是多引擎共用数据层时凭证和配置要集中管理别散落各引擎自己的配置里。第二个坑是rename操作。Hive的某些写操作会先写临时目录再rename到正式目录HDFS的rename是原子的但对象存储的rename代价非常高甚至有些对象存储直接把rename实现为copydelete文件大的时候慢到不可接受。我们当时把Hive的中间结果目录都改成了写临时目录直接覆盖写入的方式绕开rename。第三个坑是网络带宽抢用。存算分离之后大查询如果同时读取远端大量数据很容易打满网络带宽影响其他在线服务的延迟。后来我们在计算集群上做了网络限速配置并且把大查询的调度时间错峰才压住这个问题。整体来说这次改造从决定到基本稳定花了大约一个半月其中迁移和验证占了大半。收益也很清晰机器数量从两百多台降到六十多台常驻加上高峰期临时扩容存储从三副本的HDFS变成对象存储的低冗余存储整体成本降了一半以上而核心报表的延迟没有明显变化。4. 选型之前先想明白这四件事我不是劝所有人都马上做存算分离。每次有人问我要不要改我都先问四个问题这里也分享出来。4.1 你的计算负载是什么类型存算分离最适合的是分析型负载、批处理、周期性任务、弹性明显的场景。如果你的业务是超高并发的在线查询比如类似用户维度的实时查询API每次查询都是毫秒级甚至微秒级响应那存算分离的远端读取延迟大概率是扛不住的。这种业务更适合用本地存储的OLTP/OLAP引擎或者加一层高性能缓存来兜底。4.2 你的数据访问频率和热冷分布如何数据如果每天都在被高频读取和更新说明它是热数据放远端存储不划算。比如交易系统的主数据库要保证强一致性和低延迟它就不适合做存算分离。但交易库产生的历史流水、日志、归档数据放到对象存储里做离线和分析就非常合适。判断热冷分布的一个简单标准是这份数据如果超过30天没有被秒级访问的需求就可以往低成本存储层放。4.3 你的成本结构更偏向存储还是计算存算分离的价值体现在存储便宜、计算弹性。如果你的业务成本大头在计算而存储数据量并不大那么存算分离的收益就不明显。反过来如果你大部分成本都花在了存储副本和维护存储节点上那迁移到对象存储的收益会非常可观。这个判断要做量化别拍脑袋。把当前的存储成本、计算成本、闲置资源消耗都算一遍再对比迁移后的资源账单数字会告诉你答案。4.4 你的团队有没有能力处理网络和元数据的问题存算分离对网络带宽、元数据服务、缓存体系的要求比存算一体高。小团队如果运维能力有限我更推荐直接使用云上托管的产品减少自建带来的复杂度。自建Alluxio这类缓存层虽然灵活但意味着你要多运维一套分布式系统它的稳定性一样需要人负责。凡是多一套系统就多一份故障面这个账也要算进去。5. 存算分离的下一步影响范围比想象中更大最后聊一聊我对这个趋势走向的观察。存算分离不会停留在存储和计算分开这个层面它正在改变整个大数据技术栈的形态。对象存储本身在快速进化比如冷热数据分层、生命周期管理、智能缓存等能力越来越成熟。过去对象存储主要被认为是归档层但现在很多平台已经把对象存储作为主存储来用配合高性能缓存层做到接近本地存储的访问体验。这个演进对存算分离架构的落地非常关键因为它直接拉高了远端读的性能上限。Lakehouse湖仓一体的兴起也是存算分离思想的一种自然延伸。湖仓一体的核心诉求就是一份数据多种引擎共享没有存算分离这个诉求基本无法实现。所以你会看到主流的湖仓格式Iceberg、Hudi、Delta Lake在设计上都天然支持对象存储作为底层存储表的元数据独立于文件存储计算引擎随便换。从这个角度看存算分离已经成了数据平台架构的一个默认前提而不是可选项。另一个明显方向是Serverless化。计算层可以做到按需拉起、按量计费存储层独立存在这其实就是存算分离在云原生时代的最终形态。用户不再关心集群有多大、节点有多少只管写SQL和交钱。我见过不少公司已经在用这种方式跑临时分析任务用的时候创建、不用的时候销毁成本核算清晰到每次查询。如果你正在准备大数据相关的毕设或者面试我建议多关注这类真实架构决策背后的细节。面试官问存算分离不是想听你背概念而是想看你能不能说出什么场景适合、什么场景不适合、网络开销怎么控制、元数据性能怎么解决这些实操层面的东西。毕设如果能做一个简单的存算分离Demo比如用对象存储存数据、用容器化方式拉起Spark集群分析同一份数据并从成本和性能两个维度做对比这种项目放在简历上是很有说服力的。最后分享一个实用的计算方式你可以在选型时直接套用估算一下每年花在存储和计算上的总成本然后把数据增长率和业务峰值波动周期标出来。如果数据增长率明显大于计算增长率或者计算波动幅度很大那么存算分离大概率值得做。我用这个简单的判断帮好几个团队做了架构上的取舍方向基本没跑偏过。