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

数据平台上的 schema 变更,最危险的往往不是 ALTER TABLE 报错,而是 ALTER 成功、任务也能跑,结果却把旧字段读成了另一个含义。

按字段位置读取的系统里,删除第二列后,后面的列全部向前移动;按字段名读取的系统里,先删除 status,过一段时间又新建同名字段,旧文件中的 status 可能被误认为新字段。单看最新 DDL,两次操作都合法,历史数据的语义却已经混在一起。

Apache Iceberg 0.12.0 用永不复用的 Field ID 跟踪列。改名和重排只改变显示信息,字段身份不变;删除后再添加同名列会拿到新 ID,旧数据不会“复活”。这套规则很适合用来理解 schema evolution 的核心:兼容性不是比较两份字段名列表,而是判断字段身份、类型和值域能否连续解释。

Schema Evolution 从变更申请到读写验证

数据任务失败后,排查过程经常是这样的:先在调度平台找到实例,再去 YARN 搜 application,进入引擎页面找 stage,最后 SSH 到某个节点翻 container 日志。中间任何一层 ID 没记住,就只能靠任务名和时间范围碰运气。

这不是日志数量不够,而是缺少关联键。调度器、提交服务、资源管理器和计算引擎各自都有状态,却没有一条稳定标识把它们连成同一次运行。平台最后只能截取“最近 100 行”放在失败弹窗里,看起来集中,实际上丢掉了大量上下文。

我做数据任务可观测性时,第一步不会先搭新的日志检索页面,而是把 schedule_instance_id 从创建实例开始传到执行端,并在每次外部资源分配后立即保存映射。只要关联关系可靠,日志、指标、trace 和配置才有机会组成证据链。

数据任务从调度实例到运行证据的关联链

同一段 SQL,离线任务算出的订单金额是 1000 万,实时看板是 998 万。很多团队会先对 SQL 文本,确认 join、filter、group by 看起来一致,然后把差异归因成“实时有延迟”。

SQL 一致只是最表面的一层。批处理读的是一个有界快照,流处理消费的是持续变化的 changelog;两边如果没有停在同一个数据边界上,就连应该相等的时刻都没有定义。再叠加事件时间、watermark、迟到数据、UPDATE/DELETE 和 sink 主键,数值不同反而是正常结果。

Flink 1.13.1 的动态表文档有一句很重要的话:连续查询在任意时刻的结果,语义上等价于在输入表快照上执行同一批查询。这个“输入表快照”就是批流对账需要构造的参照物,而不是墙上时间写着几点。

批流对账必须统一的四层边界

“Iceberg 支持原子提交”这句话很容易被理解成:两个任务同时写同一张表也不会冲突,失败了自动重试就好。实际边界要窄得多。

Iceberg 的原子点是 table metadata pointer 从旧 metadata file 切换到新文件。数据文件、manifest、manifest list 和新 metadata file 在此之前已经写到存储上;只有 catalog 中的指针成功切换,新 snapshot 才对读者可见。两个 writer 基于同一个旧版本提交时,只能有一个先完成切换,另一个必须刷新表状态、重新验证再尝试。

所以原子性解决的是“读者不会看到半张表”,不是“所有并发操作都会成功”。并发 append、overwrite 和 compaction 的冲突条件不同,失败后的处理也不能统一写成一个无限重试。

Iceberg Snapshot 的乐观并发提交

CDC 任务第一次启动,通常要先把表里已有的数据读出来,再持续消费 Binlog。产品页面上这件事常被简化成两个阶段:全量完成,切到增量。真正的一致性问题恰好藏在“切”这个字里。

全量扫描可能持续几个小时,这期间业务仍在 INSERT、UPDATE、DELETE。先扫表、扫完以后再记 Binlog 位点,会漏掉扫描期间的变化;先记位点、等全量全部写完再读 Binlog,又必须保证这段日志不会被清理,而且下游能正确处理快照记录与后续变更。

Debezium 1.6.0.Final 的 MySQL connector 给出了一个可读的实现:在短暂锁定期间建立 repeatable read 事务,记录 Binlog 位点和表结构,然后释放全局读锁,在同一一致性视图里继续扫描表。这个位点才是全量与增量的边界。

Debezium MySQL 初始快照与 Binlog 衔接

Flink 作业平时运行正常,一到流量高峰,checkpoint duration 突然从几十秒拉长到超时。第一反应通常是 RocksDB 或 HDFS 写得慢,于是继续调 checkpoint timeout。超时时间变长以后,失败次数可能少了,恢复点却越来越旧,背压也没有消失。

Checkpoint 的端到端时间不只是“状态写入存储”的时间。barrier 从 source 往下游传递,要先穿过已有的数据和网络缓冲;多输入算子还要等各个 channel 的同一轮 barrier 到齐。上游或下游已经背压时,barrier 本身就可能走不动,状态后端甚至还没开始做主要工作。

我排查这类问题时,会先把一次 checkpoint 拆成 start delay、alignment、同步快照和异步落盘四段。只有知道时间花在哪一段,参数调整才有意义。

Flink 背压下 checkpoint 的四段耗时

一. 背景 目前公司的产品的《命令行复测结果简报》中检测出反弹shell漏洞, 需要对该问题做出相关相关应对方案。 二. 反弹shell介绍 反弹shell(reverse shell),就是控制端监听在某TCP/UDP端口,被控端发起请求到该端口,并将其命令行的输入输出转到控制端。reverse shell与teln……

一、前言 众所周知传统的 Apache Hadoop 的架构存储和计算是耦合在一起的, HDFS 作为其分布式文件系统也面临一些问题。如: 存储空间或者计算资源不足两者只能同时扩容、扩容效率低、额外增加成本、灵活性差等。本文会大家回顾Hadoop的传统架构来分析上述问题以及Hadoop实现存算分离的方案和DataSim……