本文是对《【硬刚大数据之学习路线篇】从零到大数据专家的学习指南(全面升级版)》的Hive部分补充。
1 Executor 参数
以单台服务器 128G 内存,32 线程为例。
1.1 spark.executor.cores
该参数表示每个 Executor 可利用的 CPU 核心数。其值不宜设定过大,因为 Hive 的底层以 HDFS 存储,而 HDFS 有时对高并发写入处理不太好,容易造成 race condition。根据经验
实践,设定在 3~6 之间比较合理。
假设我们使用的服务器单节点有 32 个 CPU 核心可供使用。考虑到系统基础服务和 HDFS等组件的余量,一般会将 YARN NodeManager 的 yarn.nodemanager.resource.cpu-vcores 参数
设为 28,也就是 YARN 能够利用其中的 28 核,此时将 spark.executor.cores 设为 4 最合适,最多可以正好分配给 7 个 Executor 而不造成浪费。又假设 yarn.nodemanager.resource.cpu vcores 为 26,那么将 spark.executor.cores 设为 5 最合适,只会剩余 1 个核。
由于一个 Executor 需要一个 YARN Container 来运行,所以还需保证 spark.executor.cores的值不能大于单个 Container 能申请到的最大核心数,即 yarn.scheduler.maximum-allocation vcores 的值。
1.2 spark.executor.memory/spark.yarn.executor.memoryOverhead
这两个参数分别表示每个 Executor 可利用的堆内内存量和堆外内存量。堆内内存越大,Executor 就能缓存更多的数据,在做诸如 map join 之类的操作时就会更快,但同时也会使得
GC 变得更麻烦。spark.yarn.executor.memoryOverhead 的默认值是 executorMemory * 0.10,最小值为 384M(每个 Executor)
Hive 官方提供了一个计算 Executor 总内存量的经验公式,如下:
yarn.nodemanager.resource.memory-mb*(spark.executor.cores/yarn.nodemanager.resource.cpu-vcores)
其实就是按核心数的比例分配。在计算出来的总内存量中,80%~85%划分给堆内内存,剩余的划分给堆外内存。
假设集群中单节点有 128G 物理内存,yarn.nodemanager.resource.memory-mb(即单个NodeManager 能够利用的主机内存量)设为 100G,那么每个 Executor 大概就是 100*(4/28)=
约 14G。
再按 8:2 比 例 划 分 的 话 , 最 终 spark.executor.memory 设 为 约 11.2G ,spark.yarn.executor.memoryOverhead 设为约 2.8G。通过这些配置,每个主机一次可以运行多达 7 个 executor。每个 executor 最多可以运行4 个 task(每个核一个)。因此,每个 task 平均有 3.5 GB(14 / 4)内存。在 executor 中运行的所有 task 共享相同的堆空间。
set spark.executor.memory=11.2g;
set spark.yarn.executor.memoryOverhead=2.8g;
同理,这两个内存参数相加的总量也不能超过单个 Container 最多能申请到的内存量,即 yarn.scheduler.maximum-allocation-mb 配置的值。
1.3 spark.executor.instances
该参数表示执行查询时一共启动多少个 Executor 实例,这取决于每个节点的资源分配情况以及集群的节点数。若我们一共有 10 台 32C/128G 的节点,并按照上述配置(即每个节
点承载 7 个 Executor),那么理论上讲我们可以将 spark.executor.instances 设为 70,以使集群资源最大化利用。但是实际上一般都会适当设小一些(推荐是理论值的一半左右,比如 40),
因为 Driver 也要占用资源,并且一个 YARN 集群往往还要承载除了 Hive on Spark 之外的其他业务。
1.4 spark.dynamicAllocation.enabled
上面所说的固定分配 Executor 数量的方式可能不太灵活,尤其是在 Hive 集群面向很多用户提供分析服务的情况下。所以更推荐将 spark.dynamicAllocation.enabled 参数设为 true,以启用 Executor 动态分配。
1.5 参数配置样例参考
set hive.execution.engine=spark;
set spark.executor.memory=11.2g;
set spark.yarn.executor.memoryOverhead=2.8g;
set spark.executor.cores=4;
set spark.executor.instances=40;
set spark.dynamicAllocation.enabled=true;
set spark.serializer=org.apache.spark.serializer.KryoSerializer;
2 Driver 参数
2.1 spark.driver.cores
该参数表示每个 Driver 可利用的 CPU 核心数。绝大多数情况下设为 1 都够用。
2.2 spark.driver.memory/spark.driver.memoryOverhead
这两个参数分别表示每个 Driver 可利用的堆内内存量和堆外内存量。根据资源富余程度和作业的大小,一般是将总量控制在 512MB~4GB 之间,并且沿用 Executor 内存的“二八分配方式”。例如,spark.driver.memory 可以设为约 819MB,spark.driver.memoryOverhead 设为约 205MB,加起来正好 1G。