一文讲透 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 对象。

相关推荐
guodingdingh8 小时前
软件开发工作问题总结0718
java·开发语言·数据库
咖啡八杯10 小时前
GoF设计模式——解释器模式
java·后端·spring·设计模式
优橙教育10 小时前
5G网优培训 vs Java开发:转行选哪个?
java·开发语言·5g
糖果店的幽灵10 小时前
【DeepAgents 从入门到精通】Context Management 上下文管理
java·人工智能·后端·spring·中间件·langgraph·deepagents
想会飞的蒲公英11 小时前
计算机怎样读取中文文本:编码、清洗与标准化
人工智能·python·自然语言处理
腻害兔12 小时前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:字典、短信、邮件、通知——后台系统的“基础设施四件套“!
java·前端·vue.js·产品经理·ai编程
SeaTunnel12 小时前
从 Python Script 地狱到标准化数据集成框架
大数据·开发语言·python·程序员·代码·seatunnel
深度研习笔记12 小时前
OpenCV工业视觉实战09|项目EXE打包+工控机无环境部署+后台常驻运行,彻底脱离Python环境,完成项目最终交付
python·opencv·webpack
碎光拾影12 小时前
ARM交叉工具链各工具作用及IMX6ULL平台LED+蜂鸣器裸机程序实现
java·开发语言·数据库
CCPC不拿奖不改名12 小时前
大模型推理架构与开源生态知识整理
数据库·windows·python·架构·langchain·开源·github