ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

MPP架构核心解析:从并行原理到主流数据库选型实践

MPP架构核心解析:从并行原理到主流数据库选型实践 上个月帮朋友优化一个数据看板后台那条跑了三个多小时没出结果的聚合SQL换到一套MPP集群上同样的数据量两分多钟就回来了。那一刻我意识到MPP这个概念虽然被圈内讲烂了但绝大多数人其实对它只有一个模糊印象真到选型、部署、排错的时候很多细节还是要重新捋一遍。这篇是MPP系列的第一篇先把地基打牢说清楚MPP到底是什么、它的架构核心长什么样、以及目前市面上主流的MPP平台各自支持到什么程度。适合刚接触分布式数据仓库的开发者也适合那些已经在单机数据库上被大查询折磨过、正在考虑要不要往MPP迁移的团队。1. 从一次慢查询说起MPP到底是什么1.1 一个三小时变两分钟的直观对比先复盘一下上面提到的那个案例。那套看板的底层是一个单机版的关系型数据库配置不算差32核CPU、256GB内存SSD盘。业务表大概有4亿行要按时间窗口做多维度聚合还要关联三张维表。单机数据库在执行这种查询时全表扫描加哈希关联把CPU和磁盘IO全都打满跑了三个小时也没出结果看板直接超时。后来把同样的表结构和数据迁到一套8节点的小型MPP集群每个节点16核、64GB建好分布键和分区之后同一套SQL跑下来用了不到两分钟。快出来的原因说起来也不玄乎4亿行数据被拆成8份每个节点只扫自己手上的5000万行几个维表做了复制分发关联的时候不需要大量跨节点搬数据所有节点同时干活最终结果再汇总到协调节点返回。这就是MPP的核心逻辑大规模并行处理Massively Parallel Processing把一个大任务拆成多个小任务分散到一堆独立的服务器上同时执行最后把结果合并。它不是什么高深魔法本质上跟装修请一支施工队一个道理——师傅一个人砌墙三个月来十个师傅各管一段时间自然就压下来了。1.2 MPP的准确定位与边界严格来说MPP指的是一种并行计算架构不是某一个具体的数据库产品。它描述的是一类系统的组织方式由多个节点构成每个节点有自己独立的CPU、内存和磁盘节点之间通过网络互连和通信数据和处理逻辑尽可能在本地完成。这里就容易遇到第一个混淆点MPP和普通分布式系统是一回事吗答案是相关但不等同。分布式是一个更宽泛的概念一个分布式文件系统如HDFS也是分布式的但它本身不负责并行计算一个微服务系统也是分布式的但它的目标是解耦业务逻辑不是为了把一个SQL查询拆碎了并行去跑。MPP则特指那种数据分散存储在各节点、计算任务也分发到各节点、各节点并行执行、最终结果合并的数据库或计算引擎。还有一个边界需要说清楚MPP不是OLTP的菜。一个典型的OTLP系统比如电商下单特点是大量短小的事务型SQL每次读写的数据量很小但并发极高。MPP擅长的是OLAP场景七八张大表join、几十亿行扫过去做聚合、按任意维度切片切块这种重活才是它的主场。用我常打的比方OLTP好比街边便利店一个顾客买一盒牛奶很快就走关键是要服务得快OLAP好比大型仓储超市的周末大采购一辆购物车装满各种东西结账一批算一批一次干大活。1.3 为什么单机数据库会在某一天突然扛不住聊MPP之前先理解为什么必须上MPP比理解MPP是什么更重要。单机数据库的性能天花板受三个硬件因素限制CPU的计算速度、内存的容量、磁盘的IO吞吐。单台服务器做到极致比如64核、512GB内存、NVMe全闪阵列它能支撑的数据量和计算复杂度有一个明确的上限。当一张表膨胀到几十亿行、一个聚合查询要扫描数百GB甚至上TB的数据时单机的磁盘IO就成了绕不开的瓶颈CPU再快也得等数据从盘上读出来。同时单机数据库还有个隐性痛点缓存命中率。数据量大到内存装不下之后频繁的磁盘换页会让整个系统进入一种看起来CPU不高但查询就是慢的瘫痪状态。这个阶段很多团队的第一反应是加内存、换更快的盘但这只是延缓不是解决。每加一轮硬件成本都在涨而查询复杂度和数据量还在涨总有一天你会发现这台机器已经顶在配置表的最高档位上了上面已经没有任何可以再加的硬件。MPP解决的是这个结构性难题不跟单机硬件较劲而是用多台普通机器堆成一个逻辑集群把数据和计算平摊出去。这也是很多公司从PostgreSQL或MySQL单机实例迁到Greenplum、ClickHouse这类系统最核心的驱动力。2. MPP架构的核心组件与数据流转逻辑2.1 三种并行架构对比SMP、NUMA与MPP想真正理解MPP的架构精华最好先把它放进并行架构的谱系里看。并行计算领域大体有三种经典模型。SMP对称多处理架构是最传统的一种多个CPU核心共享同一块内存和同一组IO总线操作系统把任务分配给各核心。它的优势是编程简单数据在内存里共享起来非常方便一台机器里所有核心看到的是同一个数据视图。但缺陷也很明显所有核心抢同一条内存总线核心数量一多总线带宽就成了瓶颈。SMP架构撑死了也就几十个核心再往上扩展收益急剧下降。NUMA非一致内存访问架构是对SMP的改良每个CPU核心组有自己的本地内存访问本地内存快访问别组的内存慢内存访问不再一致。它把单机的扩展性往前推了一步但还是受限于一台物理服务器能容纳的CPU和内存总量本质上仍然是在跟硬件厂商的服务器规格表较劲。MPP直接换了一套思路每个节点本身就是一台完整的计算机有自己的CPU、内存、磁盘节点之间不共享任何物理资源通过高速网络连接。这种设计叫Shared Nothing无共享架构。带来的最大好处是扩展性接近线性——存储不够了、算力不够了加节点就行不用动原有架构。代价是跨节点数据交换要走网络比本地内存慢几个数量级所以MPP系统对执行计划的优化极其敏感最怕的就是没必要的跨节点数据搬运。三者用一张表格看得更清楚架构类型资源组织方式扩展能力核心瓶颈典型场景SMP多核共享内存总线弱数十核封顶总线带宽、缓存一致性单机OLTP、小规模OLAPNUMA内存分区就近访问中单机多路扩展跨区访问延迟、物理机上限高性能单机计算MPP节点完全独立网络互连强近线性扩展网络带宽、数据分布策略大规模OLAP、数据仓库2.2 两个关键角色协调节点与计算节点MPP集群里有两类逻辑角色几乎所有MPP数据库框架都遵循这套分工。协调节点也叫Master节点或Coordinator节点是整个集群的大脑负责三件事接收客户端发来的SQL对SQL做解析、合法性检查并生成全局的执行计划把执行计划拆分成可以在各个计算节点上并行执行的子任务分发给下面的节点收集各计算节点返回的结果片段合并成最终结果集返回给客户端。计算节点在Greenplum里叫SegmentDoris里叫BEClickHouse里叫分片节点是真正存数据和跑计算的地方。每个计算节点只持有全量数据的一部分查询时各自扫描自己手头的数据分片完成局部的扫描、过滤、关联、聚合再把局部结果向上汇报。数据量越大计算节点越多的优势就越明显因为每个节点要处理的数据量是集群整体规模在均摊。需要注意的一个设计细节是协调节点本身通常不存业务数据它不参与底层的扫描聚合计算只做调度和汇总。这个设计保证了集群的横向扩展不受协调节点性能拖累——计算节点增加了整个系统算力就增加协调节点只负责分发和合并承担的负载增长相对有限。2.3 数据分布策略决定了大半的性能数据在各计算节点上怎么分布是整个MPP架构里最讲究的部分。分布策略选错了后续怎么调优都像在破洞的船上舀水。主流MPP数据库提供三类分布策略。哈希分布是最常用的一种。建表时指定一个或多个列作为分布键系统对该列的值做哈希运算根据哈希结果把行分配到对应的计算节点上。同一分布键值的数据必然落在同一个节点这个特性让基于分布键的等值关联可以在本地完成不需要跨节点搬数据。选择分布键的原则是尽量选择查询中最常作为关联条件和过滤条件的列同时该列的值要有足够的区分度避免大量数据扎堆到一两个节点。随机分布也叫轮询分布新来的数据行轮流放到各节点保证数据量上是均匀的但无法保证某列相同值的行落在同一节点。它的适用场景是那些没有明确关联键的临时表、中间结果表或者分布键尚未想清楚时的一个过渡选择。代价是后续如果要对这张表做关联大概率要发生跨节点数据重分布性能损耗很大。复制分布把小表完整复制到所有计算节点上每个节点都持有一份全量副本。这个策略对维表非常友好事实表与维表关联时每个节点拿自己本地的维表副本就能完成关联完全不产生网络传输。典型用法是星型模型里的日期维表、地区维表、产品维表这类几百MB以内的小表。实际项目中我见过太多因为分布键没选好导致性能崩盘的案例。比如把分布键设成一个几乎所有行都相同的字段那张表干脆就只有一两个节点在干活MPP直接退化成了单机。所以建表之前第一步永远是分析业务查询的特征想清楚最频繁的关联条件是什么然后把分布键交给那个字段。2.4 一次查询在集群里的完整旅程把前面几个概念串起来看一条SQL在MPP集群里具体怎么走。以Greenplum为例一个典型的带关联和聚合的查询大概分这么几步第一步客户端把SQL提交给协调节点。协调节点对SQL做解析生成语法树然后经过查询优化器产生最优的物理执行计划。这一步的执行计划不是一个紧耦合的整体而是被切分成多个切片每个切片分配给不同的计算节点并行执行。第二步各计算节点拿到自己的执行片段后开始扫描本地存储的数据。每个节点并行执行过滤条件比如按时间范围裁剪数据只扫符合条件的数据块。这一步的并行度是MPP的优势所在8个节点就是8路并行64个节点就是64路并行。第三步如果查询涉及关联且关联键与分布键不一致就得做数据重分布或广播一种是按关联键重新计算哈希把数据重新分配到对应节点一种是小表广播把维度表复制给所有节点。这一环节是整个查询链路里最容易拖慢速度的地方也是优化器反复权衡的重中之重。第四步各节点完成局部聚合和关联后向上传递中间结果。协调节点收到各个计算节点发来的结果片段做最终的合并和排序必要时做全局聚合然后把结果集返回给客户端。用快递分拣中心来类比这个流程再合适不过每个城市的分拣中心计算节点各自负责处理本市件本地数据把包裹按目的地分好类局部聚合然后打包发往总中心协调节点总中心把来自各地的包裹合并整理成最终的路由清单返回。每一层各干各的任务不交叉顶层只管汇总。3. 主流MPP平台与生态支持盘点3.1 老牌商业代表Teradata的江湖地位提到MPP数据库Teradata是绕不开的名字。它从上世纪80年代就开始做大规模并行处理数据库最早也是最有名的一体机形态的MPP产品长期统治金融、电信、零售这些对数据一致性要求极高的行业。Teradata的架构非常经典主节点解析SQL、生成执行计划存取节点AMPE并行存储和处理数据底层使用无共享架构配合专用网络连接性能和稳定性在商用产品里属于标杆级别。Teradata的问题是贵和重。一台入门级一体机动辄数百万元扩容要加硬件模块运维需要专业团队不是一般公司能承受的。而且它的生态相对封闭SQL方言与标准SQL有差异人才也难招。这些年随着开源MPP的崛起Teradata在市场上面临很大冲击大量存量客户在往开源路线迁移。但了解它的架构依然有价值因为很多后来者包括Greenplum在内核心思想都继承了Teradata那一套协调节点加计算节点数据按分布键哈希分散执行计划分片并行。3.2 开源MPP主力Greenplum的架构与能力边界Greenplum是目前最知名的开源MPP数据仓库基于PostgreSQL内核开发可以说就是PostgreSQL加了一副MPP骨架。它的协调节点就是你熟悉的PostgreSQL实例负责处理连接和SQL解析执行时把任务推给多个Segment节点并行跑。每个Segment也是一个独立的PostgreSQL实例存储一部分数据并执行本地的读写和计算。Greenplum的生态继承自PostgreSQL这意味着能用的工具链和扩展非常丰富比如可以用标准JDBC/ODBC连接、支持丰富的SQL语法、支持窗口函数和复杂分析函数。它比较适合的场景是离线数仓、大规模BI报表、复杂查询分析在几十TB到PB级别的数据规模下有不错的稳定性和性能。社区版免费但部署调优的复杂度不低尤其是分区策略、资源队列、并发负载这些都需要有经验的人去调。Greenplum的能力边界也要心里有数它不适合在线高并发场景不适合单条查询延迟要求毫秒级的场景也不适合做实时流式写入。它的定位很明确——批处理分析型数据仓库完整跑一个复杂查询要几秒到几分钟这是预期之内的表现。3.3 新一代MPP与列式存储ClickHouse的非典型MPPClickHouse这几年热度很高但它并不是一个标准意义上的MPP数据库。它的核心卖点是列式存储加向量化执行引擎单机性能极其强悍经常能在一张表上做到每秒扫描数十亿行的速度配合分布式表引擎ReplicatedMergeTree和分片机制也可以在集群模式下并行处理。但它和Greenplum那一类传统MPP有明显差异。ClickHouse的分布式能力更像是一种手动管理的分片集群建表时需要显式指定分片和副本跨节点join和分布式事务的支持相对弱适合做按时间维度分片、单表大范围扫描聚合这类日志分析、可观测性数据存储、在线分析服务等场景。如果业务需要大量多表复杂关联ClickHouse会让你写得很别扭。从选型角度看ClickHouse适合的场景是偏实时、偏单表扫描聚合、数据量极大。Greenplum适合的场景是离线数仓、复杂SQL关联分析、数据一致性要求高。两者不冲突不少团队的架构里甚至同时都有它们各管一段这一点后面选型部分再细说。3.4 云原生MPP与湖仓一体Doris和StarRocks的快速上位如果说前几年是Greenplum和ClickHouse的天下那这两年Doris和StarRocks这两个国产开源MPP数据库热度上升得非常快。它们的共同点是以MPP架构为基础自带列式存储、向量化执行、物化视图同时做了很多面向实时分析场景的优化比如支持高并发点查询、明细查询秒级返回、高效的Rollup预聚合。StarRocks的设计亮点在于CBO优化器和一套自研的向量化执行引擎复杂join的性能相比传统的MPP系统有明显提升加上支持外表联邦查询可以直接查Hive表、Iceberg表等湖上数据所以它在湖仓一体场景里非常受欢迎。Doris同样定位在实时数仓加湖仓一体社区活跃度高很多互联网公司拿它做用户行为分析、BI加速引擎和实时报表的平台底座。如果你的场景是希望从数据产生到报表可见的延迟控制在秒级到分钟级同时又要能支撑复杂多维分析新一代MPP数据库大概率比传统MPP和ClickHouse更顺手。不过它们也各有取舍比如对超大结果集的深度复杂关联、对事务的支持还是要看具体版本和场景。下面把几类平台的核心差异摆在一起方便快速对照平台架构内核优势场景主要限制典型用户Teradata传统MPP一体机金融、电信核心数仓成本极高、生态封闭大型政企GreenplumPostgreSQL内核MPP离线数仓、复杂SQL分析不适合高并发、调优复杂中型以上数据团队ClickHouse列式存储分布式分片日志分析、单表聚合、实时分析多表join弱、事务弱互联网、可观测性平台StarRocks/Doris新一代MPP向量化实时数仓、湖仓一体、高并发查询生态还在成熟期互联网、新零售、BI平台4. 选型决策与部署调优的实操要点4.1 三个关键问题帮你快速做MPP选型选型这件事最怕的是盲目跟风看别人上了MPP自己也上结果做出来的架构和业务场景完全不匹配。我一般会建议团队先用三个问题筛一遍。数据量到底有多大全表扫描一次要扫多少GB如果数据总量在几百GB以内单机数据库加上合适的索引、分区和归档策略大概率够用没必要上MPPMPP的运维成本和复杂度对小型团队来说是负担。一旦过了TB级别或者数据增长速度很快3到6个月内就会突破单机处理能力边界那时候就需要MPP打底。查询的复杂度和时延要求是怎样的每天最重的那几条查询要跑多久如果重的是一条涉及四五个表关联、做十几个维度聚合的报表类SQLMPP是合理选择如果主要场景是按键查一行、要毫秒级返回的在线查询MPP并不擅长不如用单机数据库或键值存储。如果查询靠的是提前聚合好的预计算结果而不是现场算那可能物化视图和OLAP缓存才是正解。团队有没有能力承接MPP的运维开源MPP系统的部署、备份、调优、故障排查都需要专门的技能积累。比如Greenplum的镜像配置、节点替换、资源队列设置做不好就会成为一种负担。没有专职数仓工程师的团队我更建议优先考虑云厂商的托管MPP服务用云服务商替你把底层运维扛下来把精力花在数据建模和业务分析上。4.2 部署时几个最容易拍脑袋犯的配置错误MPP部署的细节非常影响最终性能这里分享几个实践中经常踩的坑。节点数量不是越多越好。计算节点多了并行度确实提升但协调节点的合并开销、网络交换机带宽的争抢也会加剧。一个常见的经验是节点的单核性能和内存容量先满足单节点查询的合理内存预算再去考虑加节点。比如单条大查询涉及排序或哈希聚合每个节点至少要能容纳2到4GB的算子工作内存节点内存太小就算加了节点也会频繁发生落盘。分布键的选择绝不能不调研就拍板。建表时分布键一旦选错后面改起来成本极高因为要重建整张表。分布键的选择标准前面说过要高频关联列、高基数列、避免热门值倾斜。我亲眼见过一张订单表用订单状态作分布键结果某几个状态的订单量占了90%那90%的数据全堆在少数几个节点上查询速度惨不忍睹。分区策略要和分布键配合起来。分布键解决的是数据在节点间的均匀分散分区解决的是每个节点内部数据的裁剪能力。比如一张按日期分区的日志表每天一个分区查询只扫最近7天那么每个节点都能借助分区裁剪把扫描量缩小到原来的一小部分。分区键和分布键是两个维度的优化不要搞混。表关联时要有意识地让小表广播或复制。某些MPP系统对大小表关联有自动优化CBO在估算成本后会自动选择广播小表或重分布大表。但有些情况优化器会估错这时候就要靠人工修改会话参数或给表添加复制分布来强制走最优路径。这类优化需要结合explain查看执行计划来逐一确认。5. 常见故障排查实录与调优心得5.1 数据倾斜的定位方法数据倾斜是最典型也最让人头疼的MPP问题表现为集群里有一个节点CPU打满、磁盘IO拉满其他节点都在摸鱼整个查询的耗时被拖到某个节点的处理能力上。排查思路很简单先确认是不是分布不均匀。在Greenplum里可以直接执行select gp_segment_id, count(*) from 表名 group by gp_segment_id查看数据分布情况。正常情况下每个段的行数应该大致接近如果某几个段明显比其他段多出数倍就是分布键选得不合适。这时候需要回看表定义和业务数据特征换一个基数字段做分布键或者考虑在分布键上再加一个盐值列做组合键来打散热点。还有一种数据倾斜是运行时产生的。两个表join时如果关联键的热门值在某个维度上特别集中即使建表分布是均匀的重分布阶段仍然会有部分节点承担更多数据。这种情况需要从SQL层面解决比如把热门的那个key单独拆出来处理或者对倾斜值做加盐改造让计算能平均分摊到所有节点。5.2 网络交换瓶颈与关联重分布优化MPP查询慢的第二大原因是网络传输量太大。两个大表关联时如果关联键不是两张表的分布键系统必须在执行计划中插入一个重分布节点把两边的数据都按关联键重新哈希通过网络发送到目标节点。这一下就要传输两张表的数据量网络很容易成为瓶颈。排查方法是用explain看执行计划里的Motion节点数量。Motion是Greenplum这类MPP系统里做跨节点数据传输的算子Motion越多、传输的数据量越大查询越慢。优化手段通常有两个方向一是从根上避免Motion让两表的分布键与关联键保持一致这样关联全部落在本地节点二是无法避免时尽量把其中一个表做成复制表用一次广播替代全量重分布网络传输量能下降一个数量级。实测中一个典型的优化案例两张各几十亿行的大表按日期关联两张表原本都用用户ID做分布键每次关联都要重分布。后来把日期字段加进两表分布键的维度里重新设计分布策略将关联键改为分布键之一重分布Motion直接消失查询从40多秒降到6秒。多数的MPP性能问题追到底都是不该搬的数据在搬。5.3 资源竞争与小查询拖垮大查询随着集群上跑的查询越来越多另一个高频问题是资源竞争。如果没做资源管控大查询会把所有节点的内存和CPU全部占满小查询只能在后面排队整个集群的响应速度会变得非常不稳定。尤其是有夜间批量任务和白天报表查询混跑的场景这个问题格外突出。解决方案是把集群的资源分成多个资源队列。比如给ETL批处理队列分配70%的资源给在线报表队列分配20%给临时查询队列分配10%并对每个队列设置并发限制。大查询在批处理的队列里跑报表查询走自己的队列各管各的不再互相干扰。这个设计和操作系统的进程优先级管理思路其实是同一回事把有限的计算资源按重要程度隔离开。实际配置时注意队列的CPU使用权限和内存使用上限要同时设置只限并发不限内存照样会出现内存被大查询耗尽的情况。不同MPP厂商的资源管理接口不一样Greenplum用resource queue和resource groupDoris用Workload GroupClickHouse用自定义查询限流原理都是同一套找到对应文档做配置即可。5.4 常见问题速查表现象可能原因快速排查思路某个节点CPU/磁盘异常高分布键倾斜热点数据集中按节点ID统计行数分布确认是否均匀关联查询特别慢关联键与分布键不一致触发重分布查看执行计划Motion节点数量评估传输量大查询频繁落盘算子内存不足并行度设置过高调低statement内存并行度或增加节点内存集群整体响应不稳定大查询抢占全部资源配置资源队列隔离批处理和在线查询查询结果返回慢但各节点正常协调节点成为合并瓶颈检查结果集大小增加协调节点资源或优化SQL减少返回量数据写入后查询不到副本同步延迟或写入段失败查看集群状态和副本同步进度必要时执行平衡操作这一套排查下来百分之八九十的性能问题都能定位到根源。做MPP运维最忌讳的是看见慢就盲目加节点不动SQL不动分布策略节点加得再多倾斜问题还在该慢照样慢。我自己这一段实践下来最大的体会是MPP不是拿来即用的银弹它是一个需要理解和经营的系统。能不能发挥出它应有的性能很大程度上取决于前期建模设计是否扎实、有没有把分布键和分区想透、有没有对执行计划保持敏感。更重要的是要清楚它应该站在你技术体系里的哪个位置解决哪一类问题用什么标准去衡量它做得好不好。这篇先把概念和架构的底子打好了接下来几篇我打算沿着真实项目里的建模、调优和迁移案例逐一展开把那些文档里不会写得太细的经验拿出来拆开聊。
返回列表