远程 Shuffle 服务
本节说明如何结合 Celeborn 运行 HivePlus 以实现远程 shuffle 服务。请参阅 远程 Shuffle 服务 了解简介。
配置 MR3 使用 Celeborn
用户可以通过在tez-site.xml中设置以下配置键来配置 MR3 使用 Celeborn。内部形式为tez.celeborn.XXX.YYY的配置键被转换为celeborn.XXX.YYY并传递给 Celeborn 客户端。
tez.celeborn.enabled应设置为 true。tez.celeborn.master.endpoints应设置为 Celeborn master endpoints。tez.celeborn.client.shuffle.compression.codec应设置为none,以便中间数据不被 Celeborn 压缩。将其设置为 true 也可以,但没必要,因为我们建议使用 Tez 来压缩中间数据(将tez.runtime.compress设置为 true)。
此外,用户应在mr3-site.xml中设置以下配置键。
-
mr3.dag.vertex.schedule.by.stage应设置为 true。然后 Vertex 在所有源 Vertex 完成后才创建任务,符合 Celeborn 假设的执行模型。(如果由于某种原因将其设置为 false,则应将配置键mr3.taskattempt.queue.scheme设置为spark。) -
mr3.dag.route.event.after.source.vertex应设置为 true。然后 Vertex 仅在所有源 Vertex 完成后才接收事件。作为一个小优化,来自不成功尝试的事件会被自动阻止。
下面介绍 tez-site.xml 中的三个配置键,用于调整 reducers 内部 fetcher 的行为(这些 fetcher 向 Celeborn workers 请求中间数据)。为了说明这些配置键的用法,假设以下场景。在使用 10TB 规模因子的 TPC-DS 基准测试运行 HivePlus 时,实际观察发现会出现类似的情况。
- 源 Vertex 创建 1000 个 mappers,每个 mapper 为某个分区生成 70MB 的中间数据。
- 每个 mapper 在第一次尝试时都成功了。
- 因此 mappers 为给定分区生成的中间数据总量为 1000 * 7MB = 70GB。
tez.runtime.celeborn.fetch.split.threshold
此配置键指定 fetcher 可以从 Celeborn workers 接收的最大数据大小。Celeborn 允许单个 fetcher 接收发送到 reducer 的全部中间数据。然而,在上述场景中,这样的 fetcher 很容易成为性能瓶颈,因为通过顺序从 Celeborn workers 获取会创建单个 70GB 的 spill 文件。通过调整tez.runtime.celeborn.fetch.split.threshold,用户可以创建多个 fetcher,这些 fetcher 可以同时从 Celeborn workers 获取数据。
默认值为1024 * 1024 * 1024(1GB)。在上述场景中,默认值导致至少 70 个 fetchers。
tez.runtime.celeborn.unordered.fetch.spill.enabled
默认情况下,此配置键设置为 true,这意味着 reducers 在处理之前首先将 mappers 的输出写入本地磁盘。如果设置为 false,reducers 直接处理通过无序边获取的 mappers 输出,而不写入本地磁盘。由于典型查询产生的无序边比有序边多得多(例如由于使用order by),用户可以消除大部分写入本地磁盘的操作。在 TPC-DS 基准测试的情况下,超过 95% 的写入本地磁盘的操作被消除。
需要注意的是,即使将此配置键设置为 false,MR3 仍然需要本地磁盘用于有序边,因为 reducers 会将 mappers 的输出存储在本地磁盘上。
如果此配置键设置为 false,则先前的配置键tez.runtime.celeborn.fetch.split.threshold与无序边无关。
Celeborn 与 MR3 配合使用
以下是使用 Celeborn 时的一些实践经验。
- 尽管使用了流水线 shuffling(用于有序和无序边),推测执行与 Celeborn 配合良好(因为我们将
mr3.dag.route.event.after.source.vertex设置为 true),并且在 消除获取延迟 方面可能有效。 - 使用 Celeborn 时,将
hive-site.xml中的hive.mr3.delete.vertex.local.directory设置为 true 是安全的(或在mr3-site.xml中将mr3.am.notify.destination.vertex.complete设置为 true),因为 mappers 生成的中间数据从不写入本地磁盘。 - 运行 HivePlus 时,如果
OutOfMemoryError主要由于使用过多 fetchers 而发生,则不建议将OutOfMemoryError包含在mr3.am.task.no.retry.errors的值中,因为重新执行查询可能会以相同的OutOfMemoryError结束。在这种情况下,尝试使用较小的tez.runtime.shuffle.total.parallel.copies值。 - 自动并行度 与 Celeborn 配合良好,但自动并行度的 shuffling 优化与 Celeborn 无关。
容错
从 Celeborn 0.5.1 开始,MR3 支持使用 任务/Vertex 重运行 实现容错。因此,在配置 Celeborn 时可以安全地禁用数据复制。(在 Celeborn 0.5.1 之前,MR3 需要 Celeborn 进行数据复制以支持容错。)
为了启用使用任务/Vertex 重运行的容错,请在tez-site.xml中将配置键tez.runtime.celeborn.client.fetch.throwsFetchFailure设置为 true,以便 MR3 在发生获取失败时抛出异常并触发任务/Vertex 重运行。如果tez.runtime.celeborn.client.fetch.throwsFetchFailure设置为 false,则永远不会触发任务/Vertex 重运行,MR3 依靠 Celeborn 进行数据复制以支持容错。
当 MR3 无法使用 Celeborn 时
MR3 只能在 DAGAppMaster 和 ContainerWorkers 都作为单独的 Java 进程创建时使用 Celeborn。具体来说,在以下条件下 MR3 无法使用 Celeborn:
- DAGAppMaster 以 LocalThread 模式运行。
- ContainerWorker 以 Local 模式运行。
即使使用 Celeborn,如果 Celeborn 拒绝接受 shuffle 请求(例如,当 MR3 在消耗了 Celeborn workers 中过多磁盘空间后超出分配给它的配额),MR3 可能仍需使用自己的 shuffle handlers 或 Hadoop shuffle 服务。在这种情况下,MR3 会根据tez-site.xml中配置键tez.am.shuffle.auxiliary-service.id的值回退到 MR3 shuffle handlers 或 Hadoop shuffle service。假设这种情况很少发生,我们建议以下设置:
- 在 Hadoop 上运行 HivePlus 时,在
tez-site.xml中将tez.am.shuffle.auxiliary-service.id设置为mapreduce_shuffle,并在hive-site.xml中将hive.mr3.use.daemon.shufflehandler设置为 0,以避免在 ContainerWorkers 内创建不必要的 shuffle handlers。 - 在 Kubernetes 上或独立模式下运行 HivePlus 时,在
tez-site.xml中将tez.am.shuffle.auxiliary-service.id设置为tez_shuffle,并在hive-site.xml中将hive.mr3.use.daemon.shufflehandler设置为 1,以最大程度地减少 shuffle handlers 的内存消耗。