AWS EMR Tez Counters 配置调整

问题背景

https://miro.medium.com/v2/resize:fit:720/format:webp/1*28VzB4nqdBQKjaz9UJaDyw.png 

在运行复杂 Hive 查询时,可能遇到以下错误:

Too many counters: 1201 max=1200

这是因为 Tez 任务产生的 Counter 数量超过了配置限制。

Counter 是什么

Counter 是 Tez/MapReduce 用来收集任务执行统计信息的机制:

示例 Counter:
- INPUT_RECORDS_PROCESSED: 1000000
- OUTPUT_RECORDS: 500000
- BYTES_READ: 1073741824
- SHUFFLE_BYTES: 536870912
- CPU_MILLISECONDS: 45000

何时会产生大量 Counter

  1. 大量 DISTINCT 聚合

    SELECT 
      COUNT(DISTINCT col1),
      COUNT(DISTINCT col2),
      COUNT(DISTINCT col3),
      ...  -- 每个 DISTINCT 会产生多个 counter
    FROM table;
    
  2. 大量 GROUP BY 列

    SELECT col1, col2, col3, ..., COUNT(*)
    FROM table
    GROUP BY col1, col2, col3, ...;
    
  3. 复杂的 JOIN 操作

    • 多表 JOIN 会为每个表产生 counter
  4. 动态分区写入

    • 写入大量分区时,每个分区产生 counter

为什么要限制 Counter 数量

  1. 内存保护

    • 每个 counter 占用内存
    • 太多 counter 会导致 Application Master 内存溢出
  2. 性能考虑

    • Counter 需要序列化和传输
    • 太多 counter 影响性能
  3. 合理性检查

    • 如果产生上千个 counter,通常说明查询设计有问题

何时需要增加这个值

✅ 合理场景

  1. 复杂的 ETL 任务

    • 需要大量统计信息
    • 多个数据源合并
  2. 宽表处理

    • 表有几百个列
    • 需要对多个列做聚合
  3. 大规模数据迁移

    • 需要详细的进度追踪

❌ 不合理场景(应该优化查询)

-- 不好的做法
SELECT 
  COUNT(DISTINCT col1),
  COUNT(DISTINCT col2),
  ...
  COUNT(DISTINCT col100)  -- 100 个 DISTINCT
FROM huge_table;

-- 更好的做法:分批处理或使用 HyperLogLog
SELECT 
  col_group,
  COUNT(DISTINCT col1),
  COUNT(DISTINCT col2)
FROM huge_table
GROUP BY col_group;

核心参数

1. tez.counters.max

  • 作用:限制单个 Tez 任务可以创建的 Counter(计数器)总数
  • 默认值
    • Tez 0.9.x (EMR 5.x):1200
    • Tez 0.10.x(EMR 7.x):1200
  • 配置文件tez-site.xml

2. tez.counters.max.groups

  • 作用:限制 Counter 组的数量
  • 默认值:500
  • 配置文件tez-site.xml

参考文档

配置值建议

根据使用场景选择合适的值:

场景 推荐值 说明
小型查询 1200-2000 默认值通常足够
中型 ETL 2000-5000 适度复杂的数据处理
大型复杂任务 5000-10000 宽表处理、多表 JOIN
极端情况 10000-50000 需要评估是否优化查询

配置修改方法

⚠️ 重要提醒

不建议直接 SSH 到节点修改配置文件

原因:

  • ❌ 只影响当前节点,其他节点不同步
  • ❌ 新加入的节点(Auto Scaling)不会有这个配置
  • ❌ EMR 重新配置实例组时会覆盖
  • ❌ 难以追踪配置变更历史

推荐方式:使用 EMR 配置分类(Configuration)

方法 1: EMR Console(推荐)

创建集群时配置

  1. 创建集群时,在 Software Configuration 部分
  2. 点击 Edit software settings
  3. 选择 Enter configurationLoad JSON
  4. 添加配置:
[
  {
    "Classification": "tez-site",
    "Properties": {
      "tez.counters.max": "2000",
      "tez.counters.max.groups": "1000"
    }
  }
]

修改运行中的集群

  1. EMR Console → 选择集群
  2. Configuration 标签
  3. Reconfigure 按钮
  4. 添加或修改配置:
[
  {
    "Classification": "tez-site",
    "Properties": {
      "tez.counters.max": "2000",
      "tez.counters.max.groups": "1000"
    }
  }
]

注意: tez.counters.max 是 Tez 的配置参数,必须选择 Classification: "tez-site"(不是 hive-site

  1. 保存后,重新配置实例组
    • 选择 Instance groups 标签
    • 选择 Core 或 Task 实例组
    • 点击 Reconfigure

方法 2: AWS CLI

# 创建集群时
aws emr create-cluster \
  --name "My Cluster" \
  --release-label emr-7.10.0 \
  --applications Name=Hive Name=Tez \
  --configurations '[
    {
      "Classification": "tez-site",
      "Properties": {
        "tez.counters.max": "2000",
        "tez.counters.max.groups": "1000"
      }
    }
  ]' \
  --instance-type m7g.xlarge \
  --instance-count 3

配置验证方法

根据 AWS EMR 配置传递链路,不同验证方法查看配置的不同阶段:

EMR 配置分类 → 配置文件 → HiveServer2 → Hive Session → YARN 应用(Tez AM) → Tez 任务
               ↑           ↑              ↑              ↑
             方法1        方法2          方法2          方法3/4

推荐验证策略

  • 快速验证:方法 1(配置文件)+ 方法 2(Hive SET)
  • 完整验证:方法 1 + 方法 2 + 方法 5(运行测试查询)

方法 1: 查看配置文件(验证配置是否写入)

# SSH 到 Primary Node(Master Node)
ssh hadoop@<primary-node-ip>

# 查看配置
grep -A 2 "tez.counters.max" /etc/tez/conf/tez-site.xml

# 应该看到:
# <property>
#   <name>tez.counters.max</name>
#   <value>2000</value>
# </property>

方法 2: 在 Hive 中查看运行时配置(验证服务是否加载)

-- 连接 Hive
beeline -u "jdbc:hive2://localhost:10000"

-- 查看 Tez 配置
SET tez.counters.max;

-- 应该输出:
-- tez.counters.max=2000

方法 3: 查看 YARN 应用日志(验证实际运行时配置)

# 运行一个 Hive 查询,例如:
hive -e "SELECT COUNT(*) FROM your_table;"

# 获取 Application ID
yarn application -list

# 查看应用日志
yarn logs -applicationId application_xxxxx | grep "tez.counters.max"

方法 4: 通过 Tez UI 验证

  1. 运行一个 Hive 查询
  2. 访问 Tez UI: http://<master-node-ip>:8080/tez-ui/
  3. 选择你的 DAG
  4. 点击 Configuration 标签
  5. 搜索 tez.counters.max
  6. 应该显示 2000

方法 5: 运行测试查询(最终验证)

建议拿现有的查询任务测试:

-- 运行之前失败的查询
-- 如果成功完成,说明配置生效

或 创建一个会产生 1200-2000 个 counter 的查询:

-- 这个查询会产生很多 counter
SELECT 
  col1, col2, col3, col4, col5,
  COUNT(DISTINCT col1),
  COUNT(DISTINCT col2),
  COUNT(DISTINCT col3),
  COUNT(DISTINCT col4),
  COUNT(DISTINCT col5),
  -- 添加更多列和聚合...
FROM your_large_table
GROUP BY col1, col2, col3, col4, col5;

预期结果

  • ✅ 如果配置生效(2000):查询成功完成
  • ❌ 如果未生效(1200):报错 Too many counters: 1201 max=1200

故障排查

问题 1: 配置修改后仍然报错

原因:配置未生效

解决方案

  1. 确认配置分类是 tez-site 而不是 hive-site
  2. 重新配置实例组或重启 HiveServer2
  3. 验证配置文件是否更新

问题 2: 只有部分节点生效

原因:直接 SSH 修改了配置文件

解决方案

  1. 删除手动修改的配置
  2. 通过 EMR 配置分类统一修改
  3. 重新配置所有实例组

问题 3: 通过 EMR 配置分类修改该参数后,Core/Task Node 的配置文件未更新

原因:根据 AWS EMR 设计,不同节点类型安装的组件不同,例如: Core/Task 节点主要运行 YARN 容器,不需要客户端库和配置文件;Hive/Tez 组件仅在 Primary Node 上配置。

Primary Node (Master)

  • hive-client, hive-server2, hive-metastore-server
  • tez-on-yarn
  • ✅ 包含完整的 Hive/Tez 配置文件

Core Node

  • tez-on-worker(仅运行 Tez 任务)
  • 没有 Hive 客户端组件
  • 没有 /etc/tez/conf/tez-site.xml 配置文件

Task Node

  • tez-on-worker(仅运行 Tez 任务)
  • 没有 Hive 客户端组件
  • 没有 /etc/tez/conf/tez-site.xml 配置文件

问题 4: 增加限制后仍然内存溢出

原因:Counter 太多导致 Application Master 内存不足

解决方案

  1. 优化查询,减少 Counter 数量
  2. 增加 Application Master 内存:
    {
      "Classification": "tez-site",
      "Properties": {
        "tez.am.resource.memory.mb": "4096"
      }
    }
    

参考资料

官方文档

Previous Post
No Comment
Add Comment
comment url