Hi, Community
我想发起一个初步的讨论,关于如何扩大 Flink 写入数据的并行度,并且能够分表,可选事务支持的方案。
该方案应该支持三种场景:
1) 至少一次: 不支持或者有限支持 update 的存储,通常通过查询去重。 例如 ClickHouse
2) 相同主键或分区内有序: 支持 Upsert,但不支持事务或者跨行事务的存储,例如 ElasticSearch, MongoDB
3) 事务:支持跨行事务的存储,例如 MySQL。
另外说一下,第二种情况和第三种情况的一个重要区别是,当 CheckPoint 失败,第二种情况会从上一个快照重新执行,
那么会存在旧的数据可能覆盖新的数据的情况。举个例子: 假设正常情况下记录A在某个快照区间取值为
A1, A2, A3。假如在写入 A2 后快照失败,当重新执行的时候,会短暂的存在这种情况,A1 覆盖了 A2 的值。
下面是不同场景扩大并行度的方案
1) 至少一次:
在这种场景下,数据乱顺是可容忍的,只要保证最少一次,就能达到最终一致性。可以考虑多线程异步写入数据,
当异步任务过多,则等待有异步任务完成,再执行新的异步写入任务。CheckPoint需要保证所有异步任务完成
2) 相同主键或分区内有序,最少一次:
在这种场景下,如果指定了分区字段,可以将相同分区的数据放到一个 Buffer 里,相同 Buffer 的数据有序,
不同 Buffer的数据并行写入,CheckPoint的时候需要保证所有数据写入;如果没有分区,单指定了主键,可以
根据主键的 Hash Code 对 Sink 并行读取模,得到的值用于决定数据缓存到哪一个 Buffer,同样相同的 Buffer
内有序,不同的 Buffer 并行。
3) 事务:
由于已经有了通用的 Sink API,可以考虑把数据缓存到 Buffer, 在 CheckPoint 的时候,开启事务,完成写入数据,并提交。
[FLIP-143]
https://cwiki.apache.org/confluence/display/FLINK/FLIP-143%3A+Unified+Sink+API分表:
对于 MySQL, MongoDB 这类存储,可以通过分区键来定义分表规则,假如表 A 定义了分区键 B,B 有 B1, B2 两个取值,
那么得到两个分表 A_B1, A_B2.
--
*Best Regards*
*Jeremy Mei*