从0到1Flink的成长之路(二十一)-Sink

Posted 熊老二-

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从0到1Flink的成长之路(二十一)-Sink相关的知识,希望对你有一定的参考价值。

Sink

需要支持幂等写入或事务写入(Flink的两阶段提交需要事务支持)。
1)、幂等写入(Idempotent Writes)
幂等写操作是指:任意多次向一个系统写入数据,只对目标系统产生一次结果影响。
例如,重复向一个HashMap里插入同一个Key-Value二元对,第一次插入时这个HashMap发生变化,后续的插入操作不会改变HashMap的结果,这就是一个幂等写操作。
HBase、Redis和Cassandra这样的KV数据库一般经常用来作为Sink,用以实现端到端的Exactly-Once。

需要注意的是,并不是说一个KV数据库就百分百支持幂等写。幂等写对KV对有要求,那就是Key-Value必须是可确定性(Deterministic)计算的。假如设计的Key是:name + curTimestamp,每次执行数据重发时,生成的Key都不相同,会产生多次结果,整个操作不是幂等的。因此,为了追求端到端的Exactly-Once,设计业务逻辑时要尽量使用确定性的计算逻辑和数据模型。

2)、事务写入(Transactional Writes)
Flink借鉴了数据库中的事务处理技术,同时结合自身的Checkpoint机制来保证Sink只对外部输出产生一次影响。大致的流程如下:
第一、Flink先将待输出的数据保存下来暂时不向外部系统提交;
第二、等到Checkpoint结束时,Flink上下游所有算子的数据都是一致的时候,Flink将之前保存的数据全部提交(Commit)到外部系统。
换句话说,只有经过Checkpoint确认的数据才向外部系统写入。
如下图所示,如果使用事务写,那只把时间戳3之前的输出提交到外部系统,时间戳3以后的数据(例如时间戳5和8生成的数据)暂时保存下来,等待下次Checkpoint时一起写入到外部系统。这就避免了时间戳5这个数据产生多次结果,多次写入到外部系统。

在这里插入图片描述
在事务写的具体实现上,Flink目前提供了两种方式:
1.预写日志(Write-Ahead-Log,WAL)
2.两阶段提交(Two-Phase-Commit,2PC)
这两种方式区别主要在于:
1.WAL方式通用性更强,适合几乎所有外部系统,但也不能提供百分百端到端的ExactlyOnce,因为WAL预习日志会先写内存,而内存是易失介质。
2.如果外部系统自身就支持事务(比如mysql、Kafka),可以使用2PC方式,可以提供百分百端到端的Exactly-Once。
事务写的方式能提供端到端的Exactly-Once一致性,它的代价也是非常明显的,就是牺牲了延迟。输出数据不再是实时写入到外部系统,而是分批次地提交。目前来说,没有完美的故障恢复和Exactly-Once保障机制,对于开发者来说,需要在不同需求之间权衡。

以上是关于从0到1Flink的成长之路(二十一)-Sink的主要内容,如果未能解决你的问题,请参考以下文章

从0到1Flink的成长之路(二十一)-异步IO

从0到1Flink的成长之路(二十一)-Flink Table API 与 SQL

从0到1Flink的成长之路(二十)-扩展:并行度(Parallelism)

从0到1Flink的成长之路(二十一)-Flink+Kafka:End-to-End Exactly-Once代码示例

从0到1Flink的成长之路(二十一)-Flink+Kafka:End-to-End Exactly-Once

从0到1Flink的成长之路(二十一)-Flink+Kafka实现End-to-End Exactly-Once代码示例