本技术涉及一种关系数据库(relational database,rdb)的增量同步方法。
背景技术:
::1、关系数据库将数据存放在一个或多个表(table)中,每个表由行(row)和列(column)组成。一个表中的一行称为一条记录(record)。mysql是一种应用广泛的关系数据库管理系统。2、主键(primary key)用于唯一标识表中的每一行(即每一条记录)。3、主键通常是表中的一列,例如个人信息表的“身份证号码”列,学生信息表的“学号”列等。此时在表中的每一行中,主键列的值都是唯一的,不能有重复。主键不允许包含null(空)值。4、主键也可以是表中的多列,此时称为复合主键(composite primary key,也称联合主键、组合主键)。此时复合主键所包含的列组合在一起必须是唯一的,即使单独看每一列,它们可能包含重复值。使用复合主键有助于确保数据完整性和避免重复记录。5、唯一键(unique key)用于确保表中的某一列或多列组合的值在表中是唯一的。在表中的每一行中,相应的列包含唯一的值,但允许存在null值,且允许一列包含多个null值。6、binlog(binary log,二进制日志)是一种记录mysql数据库中发生的数据更改的日志文件。binlog记录了对数据库进行的插入(insert)、更新(update)、删除(delete)等数据更改操作以及数据库结构更改。binlog以事件(event)的形式存储,每个binlog事件都包括执行时间的信息。7、数据库同步是指将数据从一个数据库复制到另一个数据库,并保持它们之间数据一致性。全量同步和增量同步是两种常见的数据库同步方法。8、现有的关系数据库的增量同步方法是基于关系数据库的二进制日志(例如基于mysql的binlog)所记录的每个日志事件(例如binlog事件)的执行时间的顺序进行,并分为以下两种。9、第一种现有技术是单分区方案。首先,读取某一时间段内的关系数据库的二进制日志,生成日志消息(例如binlog消息)。随后,将日志消息作为单一主题(topic)和单一分区(partition),将所有日志消息放在一个全局队列中依次发送给接收方,接收方数据库按照收到每个日志消息的顺序进行增量数据同步。10、单分区方案的处理效率受限,为了提高处理效率,第二种现有技术是多分区方案。首先,读取某一时间段内的关系数据库的二进制日志,生成日志消息。随后,将日志消息划分为多个主题,每个主题再划分为多个分区,按照每个日志消息所记录的数据更改对应的那一条记录的主键(称为分区因子)的哈希(hash)值进行分发,将对应同一条记录(即同一个表中的同一行)的日志消息始终放在同一个分区队列中,由多个分区队列并行发送给接收方,接收方数据库按照收到每个日志消息的顺序进行增量数据同步。多分区方案在主键或唯一键的数据变更时容易产生顺序依赖问题,导致数据一致性错误,请参见以下两个示例。11、示例一:请参阅表1,表m有2行和2列。c1列是主键字段,c2列是唯一键字段。12、
c1(主键字段)
c2(唯一键字段)
r1
13110270002
55b919dca6dccd45abb28baab5873970
r2
98572960002
6a943c149365619cdd4970ec799b6498
13、表1:表m的数据14、对表m依次做如下操作:首先,删除r1行。随后,删除r2行。最后,插入r3行,c1字段的值是13110270002(与r1行的c1字段的值相同),c2字段的值是6a943c149365619cdd4970ec799b6498(与r2行的c2字段的值相同)。这3项操作对应的日志消息如表2所示。15、
日志消息1
删除
13110270002
55b919dca6dccd45abb28baab5873970
日志消息2
删除
98572960002
6a943c149365619cdd4970ec799b6498
日志消息3
插入
13110270002
6a943c149365619cdd4970ec799b6498
16、表2:表m的数据更改对应的日志消息17、如果接收方按照日志消息1、日志消息2、日志消息3的正确顺序执行,最终表m里仅有r3行。18、如果采用现有的多分区方案并且是根据主键进行哈希分区,那么日志消息1所记录的数据更改对应的r1行的主键的哈希值等于日志消息3所记录的数据更改对应的r3行的主键的哈希值,日志消息1和日志消息3分发到同一个分区队列中,日志消息2被分发到其它分区队列中,此时无法控制不同分区队列的发送顺序。如果接收方按照日志消息1、日志消息3、日志消息2的错误顺序执行,那么日志消息3对应的插入操作将执行失败,原因是出现唯一键冲突(与应该删除但还未被删除的r2行的c2字段的值相同)。19、示例二:请参阅表3,表n有2行和8列。pk1列、pk2列、pk3列构成了复合主键,uk1列、uk2列、uk3列都是唯一键字段,sk1列、sk2列都是业务主键。20、21、22、表3:表n的数据23、对表n依次做如下操作:首先,删除r1行。随后,更新r2行,修改pk3字段的值为307。随后,更新r2行,修改uk1字段的值为a3b4c5d7。随后,删除r2行。最后,插入r3行,pk1字段的值为105,pk2字段的值为206,pk3字段的值为308,uk1字段的值为a3b4c5d7,uk2字段的值为e7f8g9h0,uk3字段的值为i1j2k3l4,sk1字段的值为s5,sk2字段的值为s6。这5项操作对应的日志消息如表4所示。24、
日志消息1
删除
101
202
303
a1b2c3d4
e5f6g7h8
i9j0k1l2
s1
s2
日志消息2
更新
104
205
307
a3b4c5d6
e7f8g9h0
i1j2k3l4
s3
s4
日志消息3
更新
104
205
307
a3b4c5d7
e7f8g9h0
i1j2k3l4
s3
s4
日志消息4
删除
104
205
307
a3b4c5d7
e7f8g9h0
i1j2k3l4
s3
s4
日志消息5
插入
105
206
308
a3b4c5d6
e7f8g9h0
i1j2k3l4
s5
s6
25、表4:表n的数据更改对应的日志消息26、如果接收方按照日志消息1、日志消息2、日志消息3、日志消息4、日志消息5的正确顺序执行,最终表n里仅有r3行。27、如果采用现有的多分区方案并且是根据主键进行哈希分区,因为复合主键由三个字段组成,任何一个字段变化则该行记录对应的分区都不同,那么日志消息1将被投递到分区a的队列中,日志消息2、日志消息3、日志消息4将被投递到分区b的队列中,日志消息5将被投递到分区c的队列中,此时无法控制不同分区队列的发送顺序。如果按照c->a->b分区的顺序依次发送日志消息,接收方就会按照日志消息5、日志消息1、日志消息2、日志消息3、日志消息4的错误顺序执行,此时日志消息5对应的插入操作将执行失败,原因是唯一键冲突(与应该删除但还未被删除的r2行的c2字段的初始值相同)。28、由以上两个示例可以发现,无论是由单一字段的主键作为分区因子,还是由多字段的复合主键作为分区因子,在多分区的增量数据同步方案中都可能由于将日志消息投递到不同分区中而导致接收方数据库出现唯一键冲突的错误情形。实际上,分区因子也可以采用唯一键(单一字段或多字段组合)、或者业务主键(单一字段或多字段组合),也会产生相同的问题。在真实生产环境中,数据库、表的设计更加复杂,分区因子的数量和依赖关系更加复杂,因此产生的数据乱序与冲突问题会更加多样,日志消息记录的日志事件的顺序和依赖关系容易被打乱,造成数据冲突,难以有效处理。29、目前无论是基于kafka的分布式消息队列方案还是flink流计算框架,均无法从根本上解决多分区因子的顺序依赖问题。apache flink是一个框架和分布式处理引擎,用于在无边界和有边界数据流上进行有状态的计算。虽然apache flink等框架提供了水印(watermark)机制用于乱序事件的时间控制,但它们缺乏对多分区因子复杂依赖关系的支持。因此设计一种在保证增量数据同步效率基础上解决任意分区因子数量的顺序依赖问题是一个既有必要又具有挑战性的问题。技术实现思路1、本技术所要解决的技术问题是:设计一种多分区场景下的增量数据高效同步方法,解决复杂分区因子间的顺序依赖问题,保障数据一致性。2、为解决上述技术问题,本技术提出了一种解决多分区因子顺序依赖的增量数据同步方法,包括如下步骤。步骤s1:读取一个时间段内的关系数据库的二进制日志,生成日志消息;在所述日志消息所涉及的表中,将每个表中不允许出现重复值的列称为该表的分区因子。步骤s2:按照对应的数据更改执行时间的顺序,依次计算每个日志消息对应的数据更改所发生行的每个分区因子的哈希值,保存每个日志消息对应的数据更改所发生的表的名称、以及每个日志消息对应的数据更改所发生行的每个分区因子的哈希值。步骤s3:按照日志消息对应的数据更改执行时间的顺序为每个日志消息安排分区,安排分区时将存在关联的日志消息安排在同一分区;如果某些数据更改之间存在顺序依赖关系,那么这些数据更改对应的日志消息之间就存在关联。步骤s4:将日志消息按照对应的数据更改执行时间的顺序保存在一个全局队列中,同时记录为每个日志消息安排的分区;利用flink的水印机制,依次处理数据更改执行时间早于当前水印时间的日志消息,由所安排的分区将该日志消息发往接收方数据库,接收方数据库根据收到的日志消息执行相应的数据更改操作;当前水印时间是指flink的水印机制的触发时间,表示系统已经可以安全地处理早于该触发时间的事件。3、进一步地,步骤s1中,关系数据库的二进制日志以事件的形式存储,每个日志事件都包括所记录的数据更改执行时间的信息;每个日志消息对应于一个日志事件,每个日志消息也包含对应的数据更改执行时间的信息。4、进一步地,步骤s1中,每个表的分区因子至少有一个;每个表的分区因子为该表的主键字段、唯一键字段、业务主键字段的部分或全部。5、优选地,步骤s3中,在为每个日志消息安排分区时还为每个日志消息生成全局版本号,全局版本号具有唯一递增的特性。6、进一步地,步骤s3中,具体分为如下三种情况。7、情况一:如果日志消息k对应的数据更改所发生的表与已保存的在前的日志消息对应的数据更改所发生的表是不同的表,则认为日志消息k与所有在前的日志消息均不存在关联,将日志消息k分发到任意分区中。8、情况二:如果日志消息k对应的数据更改所发生的表与已保存的在前的日志消息对应的数据更改所发生的表是同一个表,并且日志消息k对应的数据更改所发生行的所有分区因子的哈希值与所有在前的日志消息对应的数据更改所发生行的所有分区因子的哈希值均不相同,则认为日志消息k与所有在前的日志消息均不存在关联,将该日志消息分发到任意分区中。9、情况三:如果日志消息k对应的数据更改所发生的表与已保存的在前的日志消息对应的数据更改所发生的表是同一个表,并且日志消息k对应的数据更改所发生行的至少一个分区因子的哈希值与在前的某一个日志消息j对应的数据更改所发生行的至少一个分区因子的哈希值相同,则认为日志消息k与在前的日志消息j存在关联,将日志消息k分发到在前的日志消息j的相同分区。10、进一步地,所述将日志消息k分发到任意分区中包括将日志消息k分发到新增分区中。11、优选地,情况一还包括:为日志消息k安排分区时还为日志消息k分配全局版本号。情况二还包括:为日志消息k安排分区时还为日志消息k分配全局版本号。情况三还包括:为日志消息k安排分区时还为该日志消息k分配全局版本号,同时将在前的日志消息j以及与日志消息j存在关联的所有日志消息的全局版本号更新为与日志消息k的全局版本号相同。12、进一步地,步骤s4中,对于未达到当前水印时间的日志消息,注册定时器先暂时存储这些日志消息,直到后续当前水印时间推进到对应时间,才触发这些日志消息的处理。13、本技术还提出了一种解决多分区因子顺序依赖的增量数据同步装置,包括分区因子生成单元、分区因子缓存单元、安排分区单元、顺序处理单元。所述分区因子生成单元用于读取一个时间段内的关系数据库的二进制日志,生成日志消息;在所述日志消息所涉及的表中,将每个表中不允许出现重复值的列称为该表的分区因子。所述分区因子缓存单元用于按照对应的数据更改执行时间的顺序,依次计算每个日志消息对应的数据更改所发生行的每个分区因子的哈希值,保存每个日志消息对应的数据更改所发生的表的名称、以及每个日志消息对应的数据更改所发生行的每个分区因子的哈希值。所述安排分区单元用于按照日志消息对应的数据更改执行时间的顺序为每个日志消息安排分区,安排分区时将存在关联的日志消息安排在同一分区;如果某些数据更改之间存在顺序依赖关系,那么这些数据更改对应的日志消息之间就存在关联。所述顺序处理单元用于将日志消息按照对应的数据更改执行时间的顺序保存在一个全局队列中,同时记录为每个日志消息安排的分区;利用flink的水印机制,依次处理数据更改执行时间早于当前水印时间的日志消息,由所安排的分区将该日志消息发往接收方数据库,接收方数据库根据收到的日志消息执行相应的数据更改操作;当前水印时间是指flink的水印机制的触发时间,表示系统已经可以安全地处理早于该触发时间的事件。14、本技术取得的技术效果是:通过分析不同数据更改之间的依赖关系(即多分区因子之间的依赖关系)确定日志消息之间是否存在关联,将存在关联的日志消息安排在同一分区,采用flink的水印机制依次处理全局队列中按时间排序的的日志消息,实现多分区场景下的数据同步一致性。本技术适应复杂分区场景,支持多字段组成的复合主键、复合唯一键,适应复杂数据模型。本技术适用于大规模数据集的增量同步,适用于高并发数据处理——例如电商、金融等对数据一致性要求较高的业务场景,适合采用分布式实时计算——如用户行为日志分析、订单流水同步等场景。当前第1页12当前第1页12