资源配置
Metastore、HiveServer2 和 DAGAppMaster 的资源
为了服务来自多个用户的并发请求,三个主要组件应分配足够的资源。特别是,未能向任何这些组件分配足够的资源可能会减慢所有查询而不会报告错误。在最多 16 个并发连接的生产环境中,用户可以使用以下设置作为基准,并根据需要进行后续调整。
vi env.shHIVE_SERVER2_HEAPSIZE=16384HIVE_METASTORE_HEAPSIZE=16384
vi yaml/hive.yaml resources: requests: cpu: 8 memory: 16Gi limits: cpu: 8 memory: 16Gi
vi yaml/metastore.yaml resources: requests: cpu: 8 memory: 16Gi limits: cpu: 8 memory: 16Gi
vi conf/mr3-site.xml
<property>
<name>mr3.am.resource.memory.mb</name>
<value>32768</value>
</property>
<property>
<name>mr3.am.resource.cpu.cores</name>
<value>16</value>
</property>
如果 HiveServer2 成为性能瓶颈,用户可以增加 HiveServer2 的资源或创建多个 HiveServer2 实例,例如:
vi yaml/hive.yamlspec: replicas: 2
由于每个 DAG 在 DAGAppMaster 中消耗内存,分配给 DAGAppMaster 的内存量实际上决定了可以同时运行的 DAG 数量。用户可以通过 mr3-site.xml 中的配置键 mr3.am.max.num.concurrent.dags 控制最大并发 DAG 数量。
vi conf/mr3-site.xml
<property>
<name>mr3.am.max.num.concurrent.dags</name>
<value>32</value>
</property>
一个简单的 DAG 通常消耗不到 1GB 的内存。例如,实验表明,分配 32GB 内存给 DAGAppMaster 足以同时运行从 TPC-DS 基准测试查询 18 生成的 128 个相同 DAG。然而,复杂查询可能会生成消耗更多内存的 DAG,因此监控 DAGAppMaster 的内存使用情况很重要。
尽管 MR3 DAGAppMaster 设计为可以从 OutOfMemoryError 中恢复,我们建议保守地设置 mr3.am.max.num.concurrent.dags。
mapper、reducer 和 ContainerWorker 的资源
hive-site.xml 中的以下配置键指定分配给每个 mapper(Map Task)、reducer(Reduce Task)和 ContainerWorker 的资源(以 MB 为单位的内存和核心数)。
hive.mr3.map.task.memory.mb和hive.mr3.map.task.vcores:分配给每个 mapper 的内存(MB)和核心数hive.mr3.reduce.task.memory.mb和hive.mr3.reduce.task.vcores:分配给每个 mapper 的内存(MB)和核心数hive.mr3.all-in-one.containergroup.memory.mb和hive.mr3.all-in-one.containergroup.vcores(用于 all-in-one ContainerGroup 方案):分配给每个 ContainerWorker 的内存(MB)和核心数hive.mr3.resource.vcores.divisor:核心数的除数
hive.mr3.map.task.memory.mb 和 hive.mr3.reduce.task.memory.mb 应足够大以适应数据集的大小。否则查询可能会因 OutOfMemoryError 或 MapJoinMemoryExhaustionError 而失败。
如果多个 mapper 和 reducer 可以同时在 ContainerWorker 中运行,HivePlus 的性能通常会提高。此外,查询不太可能因 OutOfMemoryError 或 MapJoinMemoryExhaustionError 而失败,因为 mapper 或 reducer 可以使用比 hive.mr3.map.task.memory.mb 或 hive.mr3.reduce.task.memory.mb 指定的更多内存。但是,如果在 ContainerWorker 中有太多 mapper 和 reducer,性能可能会因内存分配和垃圾回收的开销增加而下降。
在以下示例中,我们为每个 mapper 和 reducer 分配 4GB 和 1 个核心。对于 ContainerWorker,我们分配 40GB 和 10 个核心,以便 10 个 mapper 和 reducer 可以同时运行。
vi conf/hive-site.xml
<property>
<name>hive.mr3.resource.vcores.divisor</name>
<value>1</value>
</property>
<property>
<name>hive.mr3.map.task.memory.mb</name>
<value>4096</value>
</property>
<property>
<name>hive.mr3.map.task.vcores</name>
<value>1</value>
</property>
<property>
<name>hive.mr3.reduce.task.memory.mb</name>
<value>4096</value>
</property>
<property>
<name>hive.mr3.reduce.task.vcores</name>
<value>1</value>
</property>
<property>
<name>hive.mr3.all-in-one.containergroup.memory.mb</name>
<value>40960</value>
</property>
<property>
<name>hive.mr3.all-in-one.containergroup.vcores</name>
<value>10</value>
</property>
我们建议将 hive.mr3.all-in-one.containergroup.memory.mb 设置为 hive.mr3.map.task.memory.mb 和 hive.mr3.reduce.task.memory.mb 的倍数。
用户可以配置 HivePlus,以便在 Beeline 连接中为每个单独查询覆盖 mapper 和 reducer 的默认值。首先,将相关配置键添加到 hive-site.xml 中配置键 hive.security.authorization.sqlstd.confwhitelist.append 指定的列表中。需要注意的是,列表的正则表达式用 | 分隔,而不是用 ,。
vi conf/hive-site.xml
<property>
<name>hive.security.authorization.sqlstd.confwhitelist.append</name>
<value>hive\.querylog\.location.*|hive\.mr3\.map\.task.*|hive\.mr3\.reduce\.task.*</value>
</property>
我们不建议将 hive.mr3.resource.vcores.divisor 添加到列表中,因为它隐含地影响 hive.mr3.all-in-one.containergroup.vcores。
重启 HivePlus 后,用户可以在 Beeline 连接中覆盖默认值。在以下示例中,第一个查询为每个 mapper 和 reducer 分配 8GB 和 2 个核心,而第二个查询为每个 mapper 和 reducer 分配 2GB 和 1 个核心。
0: jdbc:hive2://192.168.10.1:9852/> set hive.mr3.map.task.memory.mb=8192;0: jdbc:hive2://192.168.10.1:9852/> set hive.mr3.map.task.vcores=2;0: jdbc:hive2://192.168.10.1:9852/> set hive.mr3.reduce.task.memory.mb=8192;0: jdbc:hive2://192.168.10.1:9852/> set hive.mr3.reduce.task.vcores=2;0: jdbc:hive2://192.168.10.1:9852/> !run /home/hive/sample1.sql0: jdbc:hive2://192.168.10.1:9852/> set hive.mr3.map.task.memory.mb=2048;0: jdbc:hive2://192.168.10.1:9852/> set hive.mr3.map.task.vcores=1;0: jdbc:hive2://192.168.10.1:9852/> set hive.mr3.reduce.task.memory.mb=2048;0: jdbc:hive2://192.168.10.1:9852/> set hive.mr3.reduce.task.vcores=1;0: jdbc:hive2://192.168.10.1:9852/> !run /home/hive/sample2.sql
常见错误
下面我们展示资源配置中的常见错误示例。我们假设 hive.mr3.resource.vcores.divisor 设置为 1。
1. 内存未完全利用
hive.mr3.map.task.memory.mb= 1024,hive.mr3.map.task.vcores= 1hive.mr3.reduce.task.memory.mb= 1024,hive.mr3.reduce.task.vcores= 1hive.mr3.all-in-one.containergroup.memory.mb= 8192,hive.mr3.all-in-one.containergroup.vcores= 4
ContainerWorker(4 核心)可以容纳 4 个 mapper 和 reducer(每个请求 1 核心)。由于每个 mapper 或 reducer 只请求 1024MB,ContainerWorker 永远不会使用剩余的 8192 - 4 * 1024 = 4096MB 内存。结果,DAGAppMaster 报告的平均内存使用率永远不会超过 50%。
2020-07-19T10:07:28,159 INFO [All-In-One] TaskScheduler: All-In-One average memory usage = 50.0% (4096MB / 8192MB)
2. 核心未完全利用
hive.mr3.map.task.memory.mb= 1024,hive.mr3.map.task.vcores= 1hive.mr3.reduce.task.memory.mb= 1024,hive.mr3.reduce.task.vcores= 1hive.mr3.all-in-one.containergroup.memory.mb= 4096,hive.mr3.all-in-one.containergroup.vcores= 8
ContainerWorker(4096MB)可以容纳 4 个 mapper 和 reducer(每个请求 1024MB)。由于每个 mapper 或 reducer 请求 1 核心,8 - 4 * 1 = 4 个核心永远不会被使用。
3. 内存和核心都未完全利用
hive.mr3.map.task.memory.mb= 2048,hive.mr3.map.task.vcores= 2hive.mr3.reduce.task.memory.mb= 2048,hive.mr3.reduce.task.vcores= 2hive.mr3.all-in-one.containergroup.memory.mb= 9216,hive.mr3.all-in-one.containergroup.vcores= 9
在占用 4 个 mapper 和 reducer 后,ContainerWorker 不使用剩余资源(1024MB 内存和 1 个核心)。
4. ContainerWorker 的资源过大
分配给每个 ContainerWorker 的资源不应超过底层资源管理器(Kubernetes 或 Yarn)允许的最大资源。最大资源通常小于工作节点上的物理资源。例如,具有 16GB 物理内存和 4 个物理核心的工作节点可能只允许 ContainerWorker 最多使用 14GB 内存和 3 个核心。
此外,如果 ContainerWorker 以 LLAP I/O 启用的方式启动,用户还应考虑分配给 LLAP I/O 的内存(hive.mr3.llap.headroom.mb 和 hive.llap.io.memory.size)。有关更多详细信息,请参阅 LLAP I/O。