抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

YARN 页面显示队列还有容量,作业却长时间处于 ACCEPTED,或者 ApplicationMaster 已经启动、后续 Container 一直拿不到。遇到这种情况,只看“队列使用率 70%”往往不够。

调度器分配的不是一个抽象百分比,而是落到具体节点上的一组资源。任务要申请 8 GB 内存和 4 个 vCore,某个节点只剩 16 GB 内存但只有 2 个 vCore,这个节点对它仍然不可用。把所有节点的空闲内存相加,看起来还有很多容量,也不代表存在一个能容纳当前请求的节点。

还有一个更容易忽略的前提:CapacityScheduler 使用哪个 ResourceCalculator。Hadoop 3.3.0 默认的计算器只比较内存,切换到 DominantResourceCalculator 后,内存与 CPU 才以多维资源参与比较。两种模式下同一个“50% 队列”的含义并不完全相同。

YARN 队列容量、请求形状与节点碎片

一说 HDFS 小文件治理,最常见的动作是安排一个夜间任务,把昨天的文件再合并一次。这个办法能让目录暂时好看一些,却很容易变成另一条长期运行的数据链路:白天持续制造小文件,晚上再花计算和 IO 把它们重写。

我不太赞成先上合并任务。小文件是一种结果,产生它的地方可能是过细的 Hive 分区、过多的 Reducer、流任务滚动过快,也可能是同步工具为每个并发通道各写一个文件。没有先找到生产者,存量清理得越勤,平台越难看清真正的写入模型。

这篇文章以 Hadoop 3.3.0 的文档和源码为准,先确认小文件到底给 HDFS 增加了什么负担,再讨论 concat、HAR 和重写任务各自适合做什么。

HDFS 小文件从发现到治理的闭环

数据源页面显示“测试连接成功”,任务发布后仍然报表不存在、没有查询权限或连接中断,这种情况并不矛盾。测试连接通常只完成 JDBC 建连,最多证明当前网络、账号和密码能建立一个短连接。

同步任务要求更多:Reader 要执行真实 SQL,切分键需要能参与查询;Writer 要有目标表写入权限,preSql、postSql 还要通过语法检查。任务跑几个小时以后,连接空闲超时、游标、字符集和网络设备的行为也会出现。

DataX 在 2020 年底已经有两套不同深度的检查:DBUtil.testConnWithoutRetry() 和 Job 的 dryRun。把源码走一遍,就能知道页面上的绿色图标到底证明了什么。

DataX 数据源从建连到真实任务的检查层次

DataX 任务想容忍少量脏数据,通常会在 job.setting.errorLimit 里同时写条数和比例:小表不超过 10 条,大表不超过万分之一。这个意图很合理,但 2020 年底这版 DataX 并不会同时检查两条规则。

只要配置了 record,ErrorRecordChecker 就把 percentageLimit 设成 null。两个参数都写时,真正生效的只有条数。

另一个容易混淆的配置是 core.statistics.collector.plugin.maxDirtyNumber。它限制的是控制台最多打印多少条脏数据,不是任务能够容忍多少条。把这两个 max 当成同一个阈值,会得到一条“日志看起来不多,任务却突然失败”或“日志只打印几条,任务居然成功”的链路。

这篇笔记仍然使用 DataX 提交 5485fb3,提交时间是 2020 年 12 月 17 日。

DataX 脏数据采集、日志输出与阈值检查

做元数据平台时,很容易先把精力花在资产目录、业务术语和页面分类上。界面做得很完整,任务失败时却还是有人在群里问:这张表谁负责,今天是哪段代码写的,改字段会影响哪些任务?

我更愿意从这些运维问题反推元数据模型。它们有明确答案,也能用一次真实故障检验。平台先把表、任务、实例和运行证据串起来,资产目录才不会只剩一棵需要人工维护的树。

下面用 Apache Atlas 2.1.0 的源码模型做参照。对应提交是 da35519,打包时间在 2020 年 7 月。Atlas 已经提供了实体唯一标识、Process 输入输出、实体变更审计和血缘查询;运行实例仍需要平台自己建模。

面向运维的元数据与运行证据模型

同步任务偶发失败时,加几次自动重试很诱人。网络抖一下能自己恢复,值班的人也少接一条告警。问题是,重试会把整个 Task 再执行一遍。Writer 如果不具备幂等能力,一次短暂故障很可能被放大成重复数据。

DataX 对这件事并非完全没有防护。它没有根据异常类型判断“可恢复”或“不可恢复”,而是把决定权交给 Writer:只有 Writer 明确声明支持 FailOver,TaskGroupContainer 才会重建 Task。

这篇笔记核对的是 2020 年 12 月 17 日的 DataX 提交 5485fb3,距离文章日期两天。先把源码行为说清楚,再讨论调度平台应该补哪一层。

DataX Task 失败后的重试状态

DataX 任务跑慢了,很多人的第一反应是把 job.setting.speed.byte 往上调。这个动作有时有效,有时一点反应都没有,偶尔还会把目标库写得更慢。

问题出在我们很容易把它理解成一个总限速开关。DataX 启动前会用速度预算计算 Channel 数量,运行中再由每个 Channel 统计吞吐并决定要不要休眠。Reader 和 Writer 之间还有一个有界队列。任何一环跟不上,都会把前后两端拖住。

下面的代码基于 DataX 提交 30842ca,提交时间是 2020 年 11 月 9 日。这样可以避开后来版本的改动,也和这篇笔记的时间对得上。

DataX 从速度预算到运行时背压的链路

DataX 工作原理及源码解读背景: 最近在工作中接触到阿里的数据同步工具datax,通过其实现了一些数据源的数据同步功能,虽然在官方文档中了解其工作原理,但是还是对其如何实现的可扩展的架构,和不同数据源之间导入导出的原理比较感兴趣,查看网上的一些介绍并没有深入源码,所以闲暇时间查看了datax的主流程代码,对此做了一……