尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

存算分离架构深度解析:从原理到落地实践与选型指南

存算分离架构深度解析:从原理到落地实践与选型指南 别再纠结服务器配置该堆多少核、多少内存了。从数据量突破一定规模那天起你真正该解决的问题是如何让计算资源和存储资源各自独立演进而不是被一台台物理机绑死在一起。这个思路就是大数据领域常说的“存算分离”。这篇文章我会把存算分离从底层逻辑到落地实践完整拆一遍。适合正在做大数据平台规划、数仓架构升级、或者被集群扩容成本和资源利用率折磨的工程师。就算你只是刚接触大数据看完也能明白市面上的主流架构到底在解决什么问题以及为什么几乎每一家大厂最终都会走向这条路线。1. 存算一体的天花板扩容成本、资源浪费与运维噩梦存算分离这个概念不是凭空冒出来的它的对立面是传统Hadoop时代的存算一体架构。想理解存算分离到底解决了什么得先看清楚存算一体模式下的三座大山。1.1 数据增长与计算资源被迫同步扩容传统Hadoop集群里DataNode既管磁盘存储也跑计算任务。数据量增长的时候磁盘容量不够你只能往集群里加节点。但加进来的节点不只是提供存储空间还带进来了CPU、内存这些计算资源。问题是你的业务真的需要这么多CPU和内存吗大多数时候不需要。一个数据密集型平台的典型特征是数据增速远大于计算增速但你为了那点磁盘空间被迫购入了一堆闲置的算力。这种事干一次两次还能忍数据量翻几倍之后成本直接失控。1.2 存储三副本与计算空闲的结构性矛盾为了保障数据可靠性HDFS默认写三副本这意味着3倍的存储开销。你存了10PB数据实际物理占用是30PB。存储资源被大量占用但计算任务的波峰波谷极其明显——白天业务高峰期集群CPU跑到80%以上凌晨可能只有5%的利用率。存算一体的集群里你既不能把波谷期的计算资源关掉因为数据还在本地节点上又不能只扩容存储不扩容计算因为这两者是绑定的。这就形成了一个结构性矛盾存储需要24小时在线但计算只在特定时段满负荷。存算一体的架构天然无法解决这个问题只能通过超卖或者混部来缓解但缓解的代价是稳定性风险。1.3 故障恢复与滚动升级的放大效应存算一体的集群里故障的影响面会被明显放大。一个节点宕机如果上面有计算任务任务直接失败需要重跑如果这个节点同时承担了关键的存储块HDFS还要触发数据块的复制恢复产生大量网络IO。而滚动升级的时候你不得不考虑“既要重启节点又不能让存储副本数降级”操作顺序稍有问题就可能进入数据恢复风暴。做运维的同学应该深有体会存算一体的大集群每次重启一批节点都像在拆弹你永远不知道元数据恢复和计算任务调度会撞出什么火花。这些问题积累到一定程度就逼着你重新审视架构——计算能不能和存储拆开拆开之后这个系统还能不能高效运转2. 存算分离的架构本质存储、计算、元数据三者各归其位存算分离很多人把它简单理解为“把数据放到对象存储上计算集群另起炉灶”这个说法方向没错但太粗糙了。真实场景下的存算分离不是把数据搬个家那么简单它背后是一整套职责的重新划分。2.1 算力与数据不再强绑定Executor可以不认识数据所在节点存算一体时代Spark或Hive的任务调度器会尽量把计算任务调度到数据所在的节点这就是数据本地性Data Locality。因为网络IO比本地磁盘IO慢得多靠这个优化减少数据传输开销。存算分离之后计算和存储彻底解耦任务调度器不再执着于数据本地性——数据在远端对象存储或独立存储集群上任何一个计算节点都需要通过网络读取数据本地性这个概念被弱化了。但这不代表存算分离会慢。关键在于你把数据从本地磁盘搬到了远端的分布式存储系统换取的是计算集群的弹性伸缩能力。你可以用100台机器跑计算跑完就释放再也不用为了保留计算资源而承担存储成本。至于网络开销的损失用更高效的列式存储格式、更聪明的谓词下推和缓存机制来弥补。2.2 三大核心组件的职责边界一套完整的存算分离架构我会把它拆成三个核心组件来看存储层负责数据的持久化存储常见的是对象存储S3、OSS、MinIO等或独立的分布式文件系统。这块要扛住海量数据、高吞吐读写并且具备跨可用区甚至跨地域的容灾能力。存储层的可靠性不再依赖计算节点而是依赖存储系统自身的副本或纠删码策略。计算层负责跑SQL、跑Spark作业、跑机器学习训练任务。它最大的特点是无状态化——计算节点挂掉就换一批新的不需要关心数据是否在本地。这是容器化、Serverless化的前提也是存算分离相较于存算一体最本质的优势。元数据与权限层这是最容易忽略但最要命的一块。数据存在存储层之后谁拥有哪些表的读权限表的Schema由谁管理小文件怎么治理这些不能靠存储系统自身解决必须有一个独立的元数据服务来承担比如Hive Metastore、AWS Glue Catalog或者湖仓一体框架的Catalog。2.3 数据本地性取消之后性能靠什么保底存算分离刚落地的时候团队里最容易出现的声音是“这跑得比原来慢多了”。确实万兆网卡时代远端读数据的延迟仍然比本地磁盘要高全表扫描的场景差别更明显。但如果整篇架构只是“把数据放到远端然后直接读”那这个方案根本工业级落不了地。真正管用的性能兜底手段有这么几个列式存储格式Parquet、ORC这类格式可以按列裁剪只读需要的列大幅减少网络传输量。谓词下推能下推到存储层的过滤条件不要带回计算层。缓存加速热数据放到计算节点的本地SSD或内存里避免每次重复拉远端。更高规格的网络25GbE甚至100GbE网卡已经是标配网络延迟在真正高性能场景里能拉到很低。我之前调过一套对象存储弹性Spark的架构把表格式从Avro换成Parquet加上列裁剪和缓存命中优化之后查询性能比最初的裸方案快了近4倍。这个收益完全来自对存储侧能力的挖掘。3. 主流实现形态对比从HDFS存算分离到湖仓一体存算分离并不是只有“存对象存储、算用弹性集群”这一种姿势。根据数据规模、技术栈和成本约束行业内形成了几个典型形态。3.1 HDFS Federation与冷热分层方案很多存量企业数据已经跑在HDFS上短时间内全部迁到对象存储不现实。于是出现了折中方案保留HDFS作为热数据存储把冷数据转储到更廉价的存储介质或对象存储。冷热分层的关键在于——数据在冷热之间迁移的时候计算引擎感知不到变化表依然可以正常查询底层文件可能在HDFS也可能在对象存储。这个方案的核心价值在于用有限的HDFS空间跑高价值数据用低成本存储容纳全量历史数据。3.2 对象存储弹性计算云原生时代的经典组合这套组合是当前最主流、也是弹性收益最明显的一种形态。数据统一放在对象存储桶里计算层可以是临时拉起的一批Spot实例也可以是K8s上动态调度的Pod。查询时计算引擎通过S3协议直接读取数据文件。以Spark为例核心要点是Spark的FileSystem层要适配对象存储的ListObjects和GetObject的限流模型你要把Spark的临时目录、shuffle目录等尽量放到本地磁盘而不是对象存储上。否则每次shuffle都去写对象存储不仅慢而且费用感人。3.3 湖仓一体框架在存算分离中的位置Iceberg、Hudi、Delta Lake这三个框架本质上是元数据与数据组织层的增强。它们把表的数据文件组织方式、事务能力、增量读写的语义放在一个可扩展的Catalog上存储层依然可以是对象存储。也就是说湖仓一体框架填上的是存算分离架构中缺失的“表语义层”。没有它们你在对象存储上维护一堆Parquet文件的Schema变更和增量数据会痛苦无比有了它们Object Store加上计算引擎就和传统数仓的体验拉近了一大截。3.4 选型对照表形态存储侧计算侧核心优势主要限制HDFS冷热分层HDFS对象存储固定YARN集群迁移成本低存量兼容好弹性有限需运维两套存储对象存储计算集群对象存储弹性计算(Spot/K8s)弹性最佳成本随业务波动需要适配对象存储API依赖网络云数仓云厂商托管存储托管计算引擎免运维Serverless体验好厂商锁定SQL能力受限于平台湖仓一体对象存储/自建存储开源计算引擎表语义强事务与增量支持框架本身有学习成本与元数据管理开销如果你是在云上工作我建议优先考虑第三种或第四种如果机房是自建、短期内云化无望那从HDFS冷热分层开始走是最务实的路径。4. 落地过程中的真实坑点数据迁移、小文件与缓存命中纸上谈兵到此为止下面这部分是实际改造中踩过的实实在在的坑。任何存算分离的改造真正的问题往往不在架构本身而在迁移和适配中那些容易忽略的细节。4.1 数据迁移不能靠简单的distcp一把梭从HDFS往对象存储迁数据大多数人第一反应是跑个DistCp。数据量小没问题数据量一上PB级问题全来了对象存储对小文件的处理能力远不如HDFS几亿个小文件直接让List文件的操作卡成瓶颈同时大量并行写对象存储会触发限流任务失败率显著上升。正确的做法是先做文件合并把小文件合并成128MB甚至256MB级别的大文件再启动迁移。迁移过程中还要做增量校验不能指望一次全量复制之后两边就一致了。4.2 小文件治理不是锦上添花而是前置条件存算分离之后小文件的影响会被无限放大。在HDFS里NameNode内存有限小文件多了它先撑不住在对象存储里每个小文件意味着一次独立的请求List和Get请求数量过多直接表现就是“明明数据量不大查询却奇慢无比”。解决小文件的路径有两条写入侧尽量做分区桶裁剪或者定期用压缩作业把小文件合并成大文件。Iceberg这类框架本身就支持compaction机制这也是为什么我始终认为单纯的对象存储加上裸Spark不够必须有一层表格式来管理文件布局。4.3 缓存层设计不当性能不升反降前面提到缓存是抵消远端读取延迟的关键。但缓存这玩意儿不是随便加一个Redis或Alluxio就完了。计算引擎的缓存策略、节点的本地磁盘容量、数据的热点分布这三者必须放在一起设计。我见过一个有趣的案例某个团队用Alluxio做缓存加速层结果因为缓存预读策略设置得过于激进冷数据把热数据全部挤出了缓存导致热查询的缓存命中率反而下降整体性能比不用缓存时还差。后来调整策略只对最近N天的热分区开启预读缓存效果才明显回升。缓存策略的制定依据不只是“哪些数据读得多”还要结合业务周期靠数据说话。4.4 网络带宽成本与限流问题是预算表里的隐藏炸弹存算分离架构下所有计算都要通过网络拉取数据。10PB数据被扫一遍按单GB几分钱甚至几毛钱的流量费算费用极其惊人。很多团队做完存算分离改造后发现存储成本降了但流量费用和请求费用涨了总账一算没省多少。所以在方案设计阶段就要考虑数据压缩和列裁剪的能力尽量把“从存储侧拉出来的数据量”压到最低。同时配置好对象存储的访问限流策略避免某个突发的全表扫描任务把整个平台的网络出口挤爆连累其他正常业务。5. 应用场景的收益拆解弹性扩缩容、多集群共享与Serverless化最后聊一下存算分离在真实业务场景里到底能带来哪些看得见摸得着的收益。别光听概念要落实到具体场景里才知道值不值得改。5.1 场景一海量数据上的交互式即席查询业务人员写SQL做探索式分析计算任务波峰极其陡峭可能一条SQL要扫几十亿行数据但这类查询频率其实并不高。存算分离模式下你可以为这类查询临时拉起一个计算集群扫完直接释放存算一体模式下你得常备一个大集群只为了偶尔应对这种突刺式的查询负载。对于这类场景存算分离的性价比非常明显而且借助对象存储的分区裁剪和列式存储优化查询体验比以前并不会差太多。5.2 场景二多集群共享同一份数据传统架构下离线数仓集群、实时计算集群、机器学习训练集群各自维护一份数据拷贝不仅存储浪费还容易产生数据不一致的问题数仓那边刚修完一条脏数据训练集群还在用旧版本。存算分离之后所有集群都指向同一份存储上的数据权限和元数据统一管理。这种情况带来的不只是成本节约更重要的是数据一致性变成了默认属性——不需要靠同步任务去对齐数据天然就只有一个版本。5.3 场景三Serverless化的必经之路存算分离是Serverless化的大前提。Serverless的核心特征是“算力跟着请求走”这意味着计算资源必须有极强的弹性和极短的启停周期。如果数据和计算绑死在固定节点上任何Serverless都无从谈起。所以你会发现所有提供Serverless数据分析能力的平台底层必然是存算分离架构。就算你自己不用Serverless一旦计算层做到了无状态日常扩容缩容、故障替换、版本升级的复杂度都会大幅降低。5.4 场景四数据湖与数仓分层治理存算分离不仅仅解决性能成本还带来一个组织层面的好处数据治理可以把“存储数据”和“计算数据”分给不同团队负责。存储团队关心的是文件布局、生命周期、数据加密与合规留存计算团队关心的是查询引擎、SQL性能、资源队列。两个方向可以并行演进互不阻塞。6. 文件格式、引擎适配与权限同步落地前必须想清楚的三件事前面讲了很多架构层面的内容但真正到实施阶段有三个细节如果没提前想清楚后期返工会非常痛苦。6.1 文件格式统一是存算分离的分水岭存算一体时代每个业务团队很可能用各自舒服的格式存数据有的用Parquet有的用ORC有的还在用Avro或者TextFile。存算分离之后所有计算引擎都去对象存储上读文件文件格式如果不统一公共数据层基本没法建设。我的建议是新写入的数据全部统一为Parquet Snappy压缩这个组合在绝大多数引擎里兼容性和性能都表现稳定。存量数据通过迁移过程逐步转换格式不要让格式分裂问题长期存在越拖成本越高。6.2 计算引擎对对象存储的支持程度参差不齐同样一个Spark版本对HDFS和对象存储的支持完全不是一回事。用Spark读HDFS基本开箱即用读S3或OSS你需要配置对应的Hadoop FileSystem实现类、AK/SK凭据、Endpoint地址还要针对对象存储的请求模型调优参数。另外在存算分离架构下跑Spark要特别注意Executor的临时目录配置。如果把临时目录也放到对象存储上shuffle性能会急剧恶化正确做法是把shuffle落盘到计算节点的本地NVMe磁盘上只让最终结果写回对象存储。6.3 数据权限的新难题存储层权限与元数据权限的双轨制存算一体架构下HDFS文件权限基本能满足需求。换到存算分离后存储层有存储层的访问控制比如对象存储的Bucket Policy元数据层又有自己的权限模型比如Hive的库表权限、Ranger的策略。两套权限体系如果不同步很容易出现“元数据显示有权限但存储层请求直接被拒”或者反过来“数据文件能读但表和库根本查不到”。这块建议尽早引入统一的权限同步机制避免权限策略分散管理。7. 判断你的业务是否适合存算分离的几条标准我不是想劝所有人都做存算分离——它确实不是银弹。我的建议是对照下面这几条标准做一次自检如果命中两条以上才值得启动改造。数据增长速度远大于计算增长速度集群扩容纯粹是为了磁盘空间。计算负载波峰波谷差异明显或者存在明显的闲时计算和高频即时查询场景。有多个计算集群需要访问同一份数据并且不想维护多份副本。计划引入Serverless化的计算服务或者已经受够了存算一体集群的滚动升级和故障恢复操作。如果你属于那种数据量不大、集群稳定运行、业务负载四平八稳的情况那继续维持存算一体并没有问题不要为了追概念去做大改造。大数据行业有个特点架构没有绝对的好坏只有适不适合当前的业务阶段和团队能力的方案。我自己做过一次完整的存算分离改造之后最深的体会是真正的难点从来不是把数据放到远端而是让上层计算引擎、元数据、权限和缓存策略形成一套协同工作的整体。架构图上画三条线很简单但每条线之间的交互细节才是决定系统最终性能和稳定性的关键。希望这篇文章能帮你少走一些弯路。
返回列表