跳到主要内容

内存溢出错误

OutOfMemoryError 的标准解决方案是增加分配给每个 mapper、reducer 或 ContainerWorker 的内存量,或减小 Tez 中输出缓冲区的大小。请参阅故障排除以获取建议列表。

对于执行批处理查询,用户也可以尝试在 mr3-site.xml 中设置配置键 mr3.container.task.failure.num.sleeps

mr3.container.task.failure.num.sleeps

配置键 mr3.container.task.failure.num.sleeps 指定 TaskAttempt 失败后在 ContainerWorker 线程中睡眠的次数(每次 15 秒)。**对于执行批处理查询,**将其设置为 1 或更高可以极大地帮助 HivePlus 避免由于 OutOfMemoryError 导致的连续查询失败,尤其是在内存较小的工作负载集群中。这是因为 TaskAttempt 失败后,ContainerWorker 会尝试触发垃圾回收(通过分配 1GB 的数组)并暂时挂起运行 TaskAttempt 的线程,从而使后续 TaskAttempt 不太容易受到 OutOfMemoryError 的影响。

例如,考虑一个实验,我们在一个 10TB 数据集上提交 TPC-DS 基准测试的查询 14 到 18 共 12 次。由于查询 14 由两个子查询组成,我们执行总共 6 * 12 = 72 个查询。对于每个 mapper 和 reducer,我们分配 4GB,这对于数据集的规模因子来说太小了。

  • 如果配置键 mr3.container.task.failure.num.sleeps 设置为零,查询 16 和查询 18 会失败很多次,即使有 Hive 3 的查询重新执行机制。最终,72 个查询中只有 46 个成功。
  • 相比之下,如果将其设置为 2,查询 16 和查询 18 很少失败。最终,72 个查询中有 71 个成功,只有查询 18 失败一次。

将配置键 mr3.container.task.failure.num.sleeps 设置为 1 或更高的缺点是,如果某些 TaskAttempt 失败,执行查询可能需要更长时间。两种常见情况是:1) 查询重新执行机制被触发时;2) 容错机制被触发时。

  1. 查询重新执行:在第一个 DAG 失败后第二个 DAG 运行期间,ContainerWorker 中的一些线程保持空闲,从而延迟查询的完成。
  2. 容错:如果运行中的 TaskAttempt 被终止以避免 Vertex 之间的死锁,其 ContainerWorker 只会在其线程完成睡眠后才能恢复接受新的 TaskAttempt。

在内存较小的工作负载集群中,更高的稳定性远远超过偶尔的执行速度损失,因此我们建议将 mr3.container.task.failure.num.sleeps 设置为 1 或更高。在内存充足的工作负载集群中,将 mr3.container.task.failure.num.sleeps 设置为 0 通常就可以了。默认值为 0。

如果 mr3.container.task.failure.num.sleeps 设置为 1 或更高且启用了自动扩展,用户可能会看到 DAGAppMaster 在 TaskAttempt 失败时创建比必要的更多 ContainerWorker。这是因为 TaskAttempt 失败后,ContainerWorker 不会立即变为空闲,DAGAppMaster 会尝试通过创建新的 ContainerWorker 来重新调度另一个 TaskAttempt。