共计 4153 个字符,预计需要花费 11 分钟才能阅读完成。
【点击理解更少数仓常识】
市场的变幻,政策的欠缺,技术的变革……种种因素让咱们面对太多的挑战,这仍需咱们一直摸索、克服。
往年,网易数帆将继续推出新栏目「金融专家说」「技术专家说」「产品专家说」等,汇集数帆及合作伙伴的数字化转型专家天团,聚焦大数据、云原生、人工智能等科创畛域,带来深度技术解读及其在各行业落地利用等一系列常识分享,为企业数字化转型胜利提供有价值的参考。
明天由网易数帆大数据离线技术专家尤夕多带来能帮忙标准化企业级离线数仓优化存储,进步性能,且已在网易外部实际验证过的成熟技术计划,为大家提供技术思路参考。
一、Spark 企业级离线数仓面临的痛点
企业级数仓类的工作根本以 ETL 类型为主,典型的读取多张表的数据通过一系列 SQL 算子转换后写到一张表。那么除了在性能上 Spark3 曾经有了充沛的保障,剩下的应用痛点集中在了写这个环节。Hive 和 Spark2 在写这个环节也存在很多问题,比方小文件 & 文件歪斜,数据压缩率不现实,动静分区写难以优化。针对这些问题,上面咱们一一剖析以后的情况,并给出新的解决方案。
小文件 & 文件歪斜
传统的解决方案是在 SQL 前面减少一个 DISTRIBUTE BY $columns,这实质上是减少一次额定的 Shuffle 来对数据从新分区,产出的文件品质强依赖于这个 Shuffle 字段,然而在大部分场景中,数据歪斜是必然的,这造成了局部计算分区须要解决特地大的数据量,不仅带来文件歪斜问题,在性能上也会连累整个工作实现工夫。
对执行引擎有肯定理解的同学可能会用十分 hack 形式来优化 DISTRIBUTE BY rand() * files,然而这无论是咱们外部曾经复现的 rand() 导致数据不统一,还是 Spark 社区抛出来的问题:Repartition + Stage retries could lead to incorrect data,都足以证实这是一个有缺点的计划,可能会导致数据不统一,咱们该当防止这种应用形式。
除此之外,一些有教训的同学会通过取模的形式来调整歪斜的数据,比方 DISTRIBUTE BY $column % 100, $column。这是一种可行的解决方案,但存在几个缺点:
1)存在优化下限;通过优化调试很难判断最佳的取模范畴,只能给一个绝对能够承受的优化后果
2)有很大的优化代价;须要十分理解字段的数据分布状况,再通过一直调试验证最终找到较为正当的值
3)保护老本比拟高;可能过 1 个月,数据产生了一些变动,那么之前优化的取模值就变得不合理
数据压缩率不现实
传统的解决方案是在 SQL 前面减少一个 SORT BY $column,这实质上是在写之前减少一次分区内的排序来进步数据压缩率。或者联合 Shuffle 减少 DISTRIBUTE BY $columns SORT BY $columns 让雷同数据落到一个分区后再做部分排序进一步提高数据压缩率。那么问题来了,首先这也绕不过 小文件 & 文件歪斜的问题,这里就不再反复。其次传统的字典排序不能很好的保留多维场景下数据的汇集散布,这里的多维在数仓场景下能够了解成多字段。而优良的数据汇集散布能够在查问阶段进步数据文件的 Data Skipping 比例。咱们目前大部分工作都只思考工作自身的性能,须要逐步器重上游工作查问的性能,从而造成一个良好的循环。
动静分区写场景难以优化
动静分区个别呈现在写大表的工作,单天的数据量往往超过 1TB,当然从业务角度登程这是正当的,拆分区后上游工作查问非常灵活高效。然而动静分区类的工作自身优化就十分麻烦,自带小文件问题,压缩率不高,加上数据量大,这几乎就是“强强联合”。而且认真思考一下就能够发现,动静分区场景下,小文件和压缩率其实是互斥的,如果以尽可能少的文件数优先,那么咱们须要思考用分区字段作为 Shuffle 和排序字段,让雷同分区数据落到一个计算分区内,然而压缩率高下却取决于其余数据字段,造成低压缩率景象。而如果以压缩率优先,那么咱们须要思考数据字段作为 Shuffle 和排序字段,但此时雷同分区数据会落到不同计算分区,产生大量小文件。
面对这一系列问题,咱们基于 Spark3 + Z-Order 提出了以下这些解决方案,并且曾经在线上环境获得了十分好的成果。
二、Rebalance + Z-Order
2.1 计划介绍
Z-Order 是一种能够将多维数据压缩到一维的技术,在时空索引以及图像方面应用较广。Z 曲线能够以一条有限长的一维曲线填充任意维度的空间,对于数据库的一条数据来说,咱们能够将其多个要排序的字段看作是数据的多个维度,z 曲线能够通过肯定的规定将多维数据映射到一维数据上,构建 z-value 进而能够基于该一维数据进行排序。
基于最经典的应用形式 DISTRIBUTE BY + SORT BY,咱们提出了新一代的优化计划 REBALANCE + Z-Order。REBALANCE 能够在尽可能满足 DISTRIBUTE BY 语义的状况下同时解决 小文件 & 文件歪斜问题。这里用“尽可能满足”这个词是因为,文件歪斜实质上是因为计算分区歪斜导致,那么咱们把歪斜分区拆成多个的同时也就毁坏了 DISTRIBUTE BY 语义,当然这不影响数准确性,也不会带来其余问题。基于 Z-Order 算法的排序替换了默认的字典排序,容许在多维场景下持续保留多维数据的汇集散布,在进步压缩率的同时能够减速上游工作的查问性能。
(图 1 Rebalance + Z-Order)
上图展现了 Rebalance + Z-Order 运作原理,波及表的上游工作以及上游工作。首先 Rebalance 以 Shuffle 的模式存在,并在 Shuffle 读阶段做分区的拆分和合并,保障每个 Reduce 分区解决雷同规模的数据量。基于 Z-Order 的 Data Skipping 优化强依赖于文件格式,咱们晓得 Parquet 和 ORC 这类支流的列式存储格局会在写数据的同时记录数据的统计信息,比方 Parquet 默认会以 Row Group 粒度记录字段的 min/max 值,在查问这个文件的过程中,咱们会把被 Push Down 的谓语条件和这些统计值做比照,如果不满足条件那么咱们能够间接 Skip 这个 Row Group 甚至整个文件,防止拉取有效的数据,这就是 Data Skipping 过程。
2.2 案例剖析
落地到具体任务中,能够进行从 Spark2 降级到 Spark3 再做 Z-Order 优化的操作。
- Spark2 -> Spark3
在实际操作中,因为引入了一次 Shuffle,工作会多一个 Stage,但执行工夫却大幅度缩短。这是因为本来的工作在最初一个 Stage 存在数据收缩和重大歪斜的状况,导致单个计算分区解决的数据量十分大。通过 Rebalance 后,额定的 Stage 把收缩的数据打散,并且解决了歪斜问题,最终失去了 4 倍性能晋升。不过此时呈现了另一个问题,数据压缩率降落了,计算分区内的数据收缩 + 歪斜尽管跑的慢,反而有着较高的压缩率。 Spark3 + Z-Order
为了解决压缩率的问题,咱们减少了 Z-Order 优化,能够看到压缩率晋升了 12 倍,比照 Spark2 期间的工作也有近 25% 的晋升。而且因为 IO 降落,计算性能也没有因为多一次 Z-Order 变慢。从而实现同时治理工作性能,小文件以及数据压缩率的指标。三、Two-Phase Rebalance + Z-Order
3.1 计划介绍
后面咱们提到过,动静分区场景下小文件和数据压缩率其实是互斥的,然而显然相比于在业务层面的优化,咱们还是有很大的空间在引擎层面同时改善这两个痛点。咱们提出了 Two-Phase Rebalance + Z-Order,以压缩率优先的前提下尽可能减少小文件。
(图 2 Two-Phase Rebalance)
如上图,整个流程分由 2 阶段 Rebalance + Z-Order 组成,第一阶段的 Rebalance 咱们采纳动静分区字段,目标是把文件数降到最低,然而此时压缩率是不高的,第二阶段的 Rebalance 采纳动静分区字段 + Z-Order 字段,保障输入最大的压缩率,最初通过 Z-Order 实现分区内的排序。这里可能有同学会问,为什么第二阶段 Rebalance 不会产生小文件?这是因为 AQE Shuffle Read 在拆分 Reduce 分区过程中继承了 Map 程序性,也就是说 Redcue 分区拉取到的 Map 肯定是间断的,而咱们在第一阶段 Rebalance 后,间断的 Map 意味着他们领有雷同的分区值,所以咱们能够实现尽可能的防止小文件产生。3.2 案例剖析
(图 3 比照图)
上图展现了一个工作从手动优化切换到 Z-Order 优化的成果,手动优化也是采纳后面提到的 DISTRIBUTE BY + SORT BY 联合取模的形式,当然手动优化前的工作更加惨不忍睹。Two-Phase Rebalance + Z-Order 优化后,压缩率相比手动优化晋升近 13%,相比原始工作晋升近 8 倍,文件数相比手动优化降落近 3 倍,相比原始工作降落近 14 倍。与此同时,工作计算性能也有近 15% 的晋升。四、Two Phase Rebalance + Z-Order + Zstd
4.1 计划介绍
Two Phase Rebalance + Z-Order 曾经满足了优化的需要,然而因为相比手动优化会多一次 Shuffle,导致工作过程中的 Shuffle 数据量会减少。这是长期数据,在工作完结后会主动清理,但如果咱们本地磁盘冗余不够,也会呈现存储空间有余的问题。因而咱们引入了更高压缩率的算法 Zstd,在尽可能减少对工作性能影响的前提下缩小 Shuffle 过程数据量。
4.2 案例剖析
在具体案例中,两种压缩算法有一些区别,Zstd 相比于默认的 Lz4 节俭近 60% Shuffle 数据,并且测试下来无显著性能影响,这是因为 IO 大幅度缩小补救了额定的 cpu 耗时。将来,咱们的团队也会针对 Zstd 做更多的推广优化。
小结
本文介绍了咱们基于 Spark3 + Z-Order 对于企业级离线数仓类工作的优化计划,初步解决了以后在迁徙和在历史应用 Spark 的痛点。过程中也有一些领会和感悟:没有一种技术计划能够完满解决所有的问题,但咱们也要尽力去找到那个须要斗争的点,而在此之前,优化空间是微小的。
作者介绍 ——尤夕多
网易数帆大数据离线技术专家,Apache Kyuubi PMC member,Apache Spark Contributor。