前言
上期的文章中,我们主要讨论了使用flink解决数据源对比的问题。从kafka接受企业当期的报文数据,与mysql数据库中的上期数据进行对比,捕捉差异进行预警。
这最近的工作中我们准备将要处理的数据量从一个set扩展到12个set,这期间遇到了如下三个问题:
- 每个set中的区域包括多个区域的报文类型。
- 技术提出要求,当上游程序扩展set时候,我们的程序尽量最小化工作量。
- 业务逻辑发生了变化,对比mysql set的上期数据需求,改为了对比mysql set的当期需求。
下面主要分享下针对这些问题的解决方案。
每个set中的区域包括多个区域的报文类型
在之前的开发中,我们得到了解的业务逻辑是一个set区域中的报文就是一个区域的,报文格式应该一致。
而这周测试的时候发现,每个set至少有10个区划的报文,而这里的“区划”是业务上的概念,简单来说“区域”是mysql的分库策略。目前包括12个区域,而“区划”是按照企业的行政区域进行划分,一共有25个。
一个区域可能开展了多个区划的企业业务。 针对这种情况,我们主要采用了洗牌、Map、再洗牌的思路:
- 首先kafka是通过mq进行数据接受的,而每个mq对应一个set,每个mq里包含多个区域的信息。我们使用nifi从每个mq中消费报文时候,标注出这条报文来自于哪个set,然后根据报文的区划id进行洗牌,洗牌到27个标准化算子。
- 每个标准化算子会将不同格式的json“MAP”到一个json格式。
- 再根据报文的set信息,洗牌到每个set的kafka topic。
通过洗牌、Map、再洗牌,我们基本能把每个set中的报文标准化为一个格式,放入每个set对应的kafka topic中,与每个set的mysql进行对比。
当上游程序扩展set时候,我们的程序尽量最小化工作量
上一个问题解决后,我们基本屏蔽了不同区域不同报文格式的问题。
但是如果一个kafka topic源表只处理一个set数据,那么目前共有12个set的数据,我们需要横向扩展12个kafka topic,12 flink作业去处理不同set的数据。
而由于set是技术上的分库,本身调整就很频繁,每个set的数据量是不一样的,这对工作量和机器资源都会有一定的要求。 因此我们决定将每个set的数据组合到一个kafka topic上,使用一个flink作业进行处理。在mysql端,由于每个set的表结构是相同的,我们把每个set的读入到flink中,注册为一个flink源表,然后通过unionAll再组成一个源表。
我们设计了一个配置表,将kafka的topic与要比较的mysql的set信息进行绑定,如果某一天需要新增一个set的数据,只需要将这个set的mq信息发送到这个kafka的topic中,同时在配置表中增加这条set对应的topic信息,重启flink程序,就可以将新的set数据读入到flink源表,并完成unionall的操作。
业务逻辑变化
在我们已经进入测试流程后,业务发生了较大的逻辑变化,对比mysql set的上期数据改为当期数据。
而当期的业务数据是实时写入的,我们不可能像以前一样通过jdbcInputformat方法一口气将数据都读入到内存中然后注册为源表。而是要再考虑更好的方案解决这个问题。目前由于项目时间比较紧迫,我们决定暂时采用延迟消费的思路定时从kafka拉取消息,定时重启flink作业读取一个时间段内的数据。
总结
这个项目总体来说难点还是在于业务的复杂性、每个报文的数据清洗等方面。在对比方面,我们使用flink sql能够在较短的时间内完成业务需求。