一文讲透 Java 中transient的用处(结合 Flink 理解)

文章目录

  • [一、transient 是干什么的?](#一、transient 是干什么的?)
  • [二、Java 默认的序列化规则](#二、Java 默认的序列化规则)
  • [三、如果不加 transient 会怎样?](#三、如果不加 transient 会怎样?)
  • [四、Flink 中 State 的真实存储位置](#四、Flink 中 State 的真实存储位置)
  • [五、为什么 Flink State 一定要 transient?](#五、为什么 Flink State 一定要 transient?)
  • [六、哪些字段该加 transient?哪些不该?](#六、哪些字段该加 transient?哪些不该?)
  • 七、常见误区
  • 八、推荐的标准写法模板
  • 九、总结

在 Java / Flink 开发中,我们经常看到字段前面加了一个 transient

但很多人只知道"照着写",并不清楚它到底解决了什么问题

本文从 Java 序列化原理 出发,再结合 Flink State 的真实运行模型 ,一次性把 transient 讲清楚。


一、transient 是干什么的?

一句话定义:

transient 用来告诉 Java:这个字段不要参与对象的序列化与反序列化。

java 复制代码
class User implements Serializable {
    String name;
    transient String password;
}

序列化之后:

  • name 会被保存
  • password 会被忽略,反序列化后为 null

二、Java 默认的序列化规则

在 Java 中,只要满足以下条件:

  • 类实现了 Serializable
  • 字段 不是 static
  • 字段 不是 transient

👉 那么这个字段就会被 自动序列化

也就是说:

java 复制代码
private ValueState<LastPoint> lastPoint;

在 Java 看来,这只是一个普通成员变量,会跟着对象一起被序列化。


三、如果不加 transient 会怎样?

1️⃣ 普通 Java 场景

java 复制代码
ObjectOutputStream oos = new ObjectOutputStream(...);
oos.writeObject(obj);
  • transient 字段不会被写入
  • transient 字段会被写入

这是 Java 层面的规则


2️⃣ 在 Flink 中的隐蔽问题(重点)

Flink 在以下场景中,会涉及算子对象的序列化:

  • 作业下发(JobManager → TaskManager)
  • Task 重启 / failover
  • checkpoint / savepoint
  • 扩缩容(rescale)

如果你不加 transient

java 复制代码
private ValueState<LastPoint> lastPoint;

Java 会尝试序列化这个 State 句柄对象,而这通常会导致:

  • NotSerializableException
  • 作业启动失败
  • checkpoint 异常
  • failover 后状态错乱

📌 很多问题不是立刻出现,而是线上才爆


很多人以为:

ValueState 是存在这个字段里的

这是 错误的

真实结构是:

text 复制代码
Operator 对象(Java)
 └── transient ValueState handle(句柄)
        ↓
 StateBackend(RocksDB / 内存)
 └── 真正的状态数据

也就是说:

  • ValueState / ListState / MapState
    👉 只是一个"访问入口(handle)"
  • 真正的数据由 Flink StateBackend 管理

原因一:State 不是业务数据

State:

  • 不是你对象的一部分
  • 不该由 Java 序列化
  • 不该跟着对象"复制"

它的生命周期由 Flink 运行时 管理,而不是 JVM。


原因二:State 需要在运行时重新绑定

Flink 的正确流程是:

text 复制代码
new Operator()
  ↓
open()
  ↓
getRuntimeContext().getState(...)

而不是:

text 复制代码
反序列化旧对象里的 state

所以 State 字段必须:

  • transient
  • open() 中初始化

六、哪些字段该加 transient?哪些不该?

✅ 必须 / 强烈建议加 transient

  • ValueState
  • ListState
  • MapState
  • ReducingState
  • 运行时句柄(Metric、client、连接等)
java 复制代码
private transient ValueState<A> stateA;

❌ 不要加 transient

  • 配置类
  • 常量
  • 业务规则
  • 普通 POJO 字段
java 复制代码
private final TrajConfig cfg;

这些字段:

  • 需要被序列化
  • 需要在每个 task 中保持一致

七、常见误区

❌ 误区 1:不加 transient 也能跑

是的,但只是在:

  • 本地模式
  • 未开启 checkpoint
  • 未发生 failover

👉 这是延迟爆炸型 Bug


❌ 误区 2:在构造函数里初始化 State

java 复制代码
public MyFn() {
    lastPoint = getRuntimeContext().getState(...); // ❌
}

原因:

  • 构造阶段还没有 RuntimeContext
  • state 绑定信息还不存在

八、推荐的标准写法模板

java 复制代码
public class MyProcessFunction extends KeyedProcessFunction<K, IN, OUT> {

    private final Config cfg;

    private transient ValueState<A> stateA;
    private transient ListState<B> buffer;
    private transient MapState<Long, Boolean> dedup;

    @Override
    public void open(Configuration parameters) {
        stateA = getRuntimeContext().getState(
                new ValueStateDescriptor<>("stateA", A.class));
        buffer = getRuntimeContext().getListState(
                new ListStateDescriptor<>("buffer", B.class));
        dedup = getRuntimeContext().getMapState(
                new MapStateDescriptor<>("dedup", Long.class, Boolean.class));
    }
}

九、总结

transient 的本质作用:
阻止 Java 默认序列化,
让运行时资源交给运行时系统(如 Flink)管理。

在 Flink 中可以再加一句:

State 的生命周期属于 Flink,不属于 Java 对象。

相关推荐
清平乐的技术专栏12 小时前
【Flink学习】(五)Flink 并行度与任务链,任务运行核心原理
flink
枫叶林FYL12 小时前
项目九:异步高性能爬虫与数据采集中枢 —— 基于 Crawl<sub>4</sub>AI 与 Playwright 的现代化数据采集平台 项目总览
爬虫·python·深度学习·wpf
likerhood12 小时前
Java static 关键字从浅入深
java·开发语言
猫猫的小茶馆12 小时前
【Python】函数与模块化编程
linux·开发语言·arm开发·驱动开发·python·stm32
_院长大人_12 小时前
Java Excel导出:如何实现自定义表头与字段顺序的完全控制
java·开发语言·后端·excel
磊 子12 小时前
1.4CPU缓存一致性
java·spring cloud·缓存·系统
周末也要写八哥12 小时前
Eclipse 2024全流程网盘下载与安装配置教程详解
java·ide·eclipse
来恩100313 小时前
JSTL的标签库种类
java·开发语言
Miss_min13 小时前
128K长序列数据生成
开发语言·python·深度学习
love530love13 小时前
MingLi-Bench 项目部署实录:基于 EPGF 架构的工程化实践
人工智能·windows·python·架构·aigc·epgf·mingli-bench