关于在Flink批处理中数据同步的一些经验以及批处理中使用窗口函数的一些经验

在最近的项目中有使用到Flink 批处理的方式来进行数据源的数据同步。由于一些原因,并没有去使用开源的flinkx 之类的工具,而且Flink Jdbc connect 是一种基于查询数据同步,在数据同步之前必然会业务方造成查询压力的。目前在需要同步的表中,其它的表数据最高也不超过千万,但是我们源表的数据量却是达到了上亿级别。这种数据量的业务,在数据查询中一不小心就会照成查询超时,所以在大表数据同步时需要特别注意。而由于 Flink jdbc 本身设计原因,它默认是不支持条件查询的,默认均是扫描全表。所以最后是自己自定义数据源的方式来进行数据同步。
最开始的时候,我是使用分页的方式来进行数据的分段查询。这样的好处是可以减少数据库的查询压力,当主键是整形时 采用id between 方式来进行数据查询,当主键是string 时采用 limit 方式进行查询。
最终发现,当主键是自增的整形时,效果最佳。速率也最快,而当主键非整形时,会发现前面数据的limit 查询时速度还是可以,但是当数据量达到百万级别以上时,查询速率就会开始下降,表越大 后面分页查询的速率也越慢。
解决办法:
针对这种主键非整形的数据查询,我们可以采用mysql 游标方式进行数据查询,数据源设置 FetchSize 为 Integer.MIN_VALUE 只有设置这个值,数据读取的速度才能像流一样快。
那当数据源变成流的方式读取后,我们又会发现 sink 也需要整改,因为流的数据是一条条的,我们不可能是一条条的插入,只有批量插入效率才高。这个时候我们就会想到flink 的窗口函数,因为这里我并不需要水印时间 所以我这边使用的是TumblingProcessingTimeWindows 窗口。
那当我们使用这种窗口函数的时候我们总会遇到一个问题,特别是水印窗口的时候,如果数据的水印迟迟无法更新,那么窗口就无法触发计算。那给人的感觉就好像数据丢失的感觉。关于这个问题我们可以参考 https://blog.csdn.net/shirukai/article/details/117700828
那在批处理的时候使用窗口函数还有一个更关键的问题,那就是当上游数据源结束的时候,下面的窗口函数就会默认流程已经结束了,就不会再生成新的窗口,那这样的后果就是会导致最后一批数据会丢失 无法入库。
解决办法:
延迟数据源的关闭,可以在查询数据完毕后 再设置个线程休眠时间,保证最后的窗口能正常生成。

总结
1、数据源的主键最好使用自增型分布式id,例如雪花id,这样的好处是在于在数据同步的时候可以多并行度的读取
2、数据源的主键是非整形的情况下,使用分页查询进行数据查询的话,后期会出现分页数据重复的情况。因为非整形主键的索引分布是随机的,当在数据查询的时候有新数据插入时,就会偶发分页查询重复问题
3、使用replace into 代替 insert into 避免数据重复导致数据插入失败
4、在批处理中使用时间窗口函数需要注意上游数据源的结束时间,当上游数据源结束时,下游将不会继续生成窗口,为避免下游数据丢失需要延迟上游数据源的结束时间

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值