AWS EMR Tez Counters 配置调整
问题背景
在运行复杂 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
大量 DISTINCT 聚合
SELECT COUNT(DISTINCT col1), COUNT(DISTINCT col2), COUNT(DISTINCT col3), ... -- 每个 DISTINCT 会产生多个 counter FROM table;大量 GROUP BY 列
SELECT col1, col2, col3, ..., COUNT(*) FROM table GROUP BY col1, col2, col3, ...;复杂的 JOIN 操作
- 多表 JOIN 会为每个表产生 counter
动态分区写入
- 写入大量分区时,每个分区产生 counter
为什么要限制 Counter 数量
内存保护
- 每个 counter 占用内存
- 太多 counter 会导致 Application Master 内存溢出
性能考虑
- Counter 需要序列化和传输
- 太多 counter 影响性能
合理性检查
- 如果产生上千个 counter,通常说明查询设计有问题
何时需要增加这个值
✅ 合理场景
复杂的 ETL 任务
- 需要大量统计信息
- 多个数据源合并
宽表处理
- 表有几百个列
- 需要对多个列做聚合
大规模数据迁移
- 需要详细的进度追踪
❌ 不合理场景(应该优化查询)
-- 不好的做法
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(推荐)
创建集群时配置
- 创建集群时,在 Software Configuration 部分
- 点击 Edit software settings
- 选择 Enter configuration 或 Load JSON
- 添加配置:
[
{
"Classification": "tez-site",
"Properties": {
"tez.counters.max": "2000",
"tez.counters.max.groups": "1000"
}
}
]
修改运行中的集群
- EMR Console → 选择集群
- Configuration 标签
- Reconfigure 按钮
- 添加或修改配置:
[
{
"Classification": "tez-site",
"Properties": {
"tez.counters.max": "2000",
"tez.counters.max.groups": "1000"
}
}
]
注意:
tez.counters.max是 Tez 的配置参数,必须选择Classification: "tez-site"(不是hive-site)
- 保存后,重新配置实例组:
- 选择 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 验证
- 运行一个 Hive 查询
- 访问 Tez UI:
http://<master-node-ip>:8080/tez-ui/ - 选择你的 DAG
- 点击 Configuration 标签
- 搜索
tez.counters.max - 应该显示
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: 配置修改后仍然报错
原因:配置未生效
解决方案:
- 确认配置分类是
tez-site而不是hive-site - 重新配置实例组或重启 HiveServer2
- 验证配置文件是否更新
问题 2: 只有部分节点生效
原因:直接 SSH 修改了配置文件
解决方案:
- 删除手动修改的配置
- 通过 EMR 配置分类统一修改
- 重新配置所有实例组
问题 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 内存不足
解决方案:
- 优化查询,减少 Counter 数量
- 增加 Application Master 内存:
{ "Classification": "tez-site", "Properties": { "tez.am.resource.memory.mb": "4096" } }
参考资料
官方文档
- Cloudera 文档:https://docs.cloudera.com/cdp-private-cloud-base/7.3.1/troubleshooting-hive/topics/hive-troubleshooting-tez-counter-limit-exceed.html
- Apache Tez 配置:https://tez.apache.org/releases/0.10.5/tez-api-javadocs/configs/TezConfiguration.html
- EMR 配置分类:https://docs.aws.amazon.com/emr/latest/ReleaseGuide/tez-configure.html
- EMR 节点类型:https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-master-core-task-nodes.html