引言
实际的应用中,我们有可能要对无状态的 DataStream Map 保留一些信息,以供下一次 Map 计算使用。以往常规的方法可能是利用 Redis 等外部存储,但这会带来以下几个问题:
- Map 中对 Redis 的操作会带来频繁的网络 IO,造成处理时延,一旦阻塞严重,就会造成整体形同的吞吐率下降
- Map 计算依赖于外部集群的稳定性,性能无法保障
有状态计算的应用场景
典型的有状态计算应用场景有:
- Deduplication:记录所有的主键,进行整体的去重
- Window Computing:在窗口计算中存储中间状态、结果数据
- Machine Learing / Deep Learing:保存训练模型中间结果、参数
- History data access:访问历史数据进行对比等
Flink 中的有状态计算
依赖外部存储的有状态计算会有上述等问题,而相对更好的方案是,使用基于内存( 可以是JVM内存,也可以是堆外内存 )的有状态计算。Flink 正是这么做的。但相应的,这种方式虽然避免了通信带来的时延,但对状态数据的可靠性,提出了新的挑战:
- 状态数据的一致性应如何保障?
- 系统宕机之后,如何避免状态数据的丢失
- 内存大小有限,无法存储过多的数据
- 因为版本升级、代码逻辑变化等变化,可能导致状态数据无法处理
