人大金仓KFS数据同步系统中apply()方法中的关键逻辑介绍

applier模块中apply()方法的关键逻辑介绍

关键字:

Kingbase FlySync、applier、jdbcApplier、apply

关于apply()方法

apply()方法属于KFS数据同步系统中applier模块中重要的一个方法。Applier模块中,Applier为模块顶级接口,提供了applier模块的通用方法,包括apply()、updatePostion()、commit()、rollback()、getLastEvent()方法供子类实现,此外applier模块还提供了applier接口的包装类ApplierWrapper,丰富了接口的方法,并为方法提供基本实现。JdbcApplier是RawApplier的实现类,定义了数据库apply的通用行为,其他不同数据库提供了子类继承了jdbcApplier对不同数据库apply方式做不同的实现,其中包括DB2Applier、DmApplier、OracleApplier、MysqlApplier和KingbaseApplier。Apply()方法就是在jdbcApplier中实现的一个重要方法,通过该方法可以实现将extractor模块抽取并过滤的数据以DBMSEvent的写入队列或者直接写入目标数据库。

apply()方法执行流程

从代码逻辑上来看,apply()方法执行流程如下,其中的关键流程为根据event类型执行不同的封装方式:

  • 根据lastProcessedEvent参数判断当前解析事务是否已经被解析:上一次解析结束后会将解析的event存储为lastProcessedEvent,通过对lastProcessedEvent的LastFrag标记和Seqno与当前解析事务的seqno进行比较,确保当前执行的事务是否已经被执行过。
  • 设置事务开始:根据transactionStarted参数判断上一个解析事务是否已经结束,如果结束开启新的事务。
  • 根据event类型执行不同的封装方式:
  1. 如果event instanceof DBMSEmptyEvent,表示当前事务是一个空的DBMSEvent,此时判断是否需要提交之前已经解析过的事务,如果doCommit为true则提交事务。
  2. 如果header instanceof ReplDBMSFilteredEvent,表示对当前执行事务是一个被过滤的事务,同样提交之前已经解析的事务。
  3. 如果均不是以上两种情况,则获取event内部数据,如果data是一个RowChangeData,则执行applyRowChangeData,此方法可以逐条解析数据,并生成可执行的sql,提供给数据库做数据入库处理。
  4. 解析期间如果遇到数据冲突异常,则根据系统配置信息和用户定义的异常处理规则做异常处理。

关键逻辑介绍

  • 对DBMSEvent封装的解析逻辑

在extractor模块中,系统将数据封装为DBMSEvent,使数据以这种形式在工作流中进行流转,当Applier模块获取到DBMSEvent时,需要将此封装中的数据解析出来并根据数据行为组装sql语句,为数据库提供数据入库。其主要流程是:在apply()接收参数event,判断event不是一个DBMSEmptyEvent和ReplDBMSFilteredEvent后可以确保event内部存储了系统需要解析的data数据,接着通过循环从event中获取dataElem,判断dataElem为一个RowChangeData后将dataElem作为参数传入applyRowChangeData(),在applyRowChangeData()方法中循环获取data中的每一条OneRowChange作为row参数传入applyOneRowChangePreparedOptions(),applyOneRowChangePreparedOptions()方法可以从OneRowChange中获取keySpec、columnSpec、beforeImageSpec、schemaName、tableName、action、keyValues、columnValues、beforeImageValues等关键信息,根据关键信息,方法内部通过constructStatement()方法构造sql语句。并通过循环获取每一列值,通过bindColumnValues()方法中的setObject()方法绑定sql语句中的列值,通过此流程,apply()方法可以将DBMSEvent内部封装的数据解析为数据库可识别的sql语句,实现数据库的数据写入操作。

  • 冲突处理逻辑

在数据写入数据库是,如果目标端也在同步完成业务数据的写入,那么久很用可能出现数据冲突,典型的场景是,源端数据库解析出来的数据还未及时同步到目标端,此时目标端有新的业务数据写入,而此条写入数据刚好与源端同步过来的待入库数据存在主键冲突,则当源端数据入库时就会存在主键重复冲突,应对这种场景,需要进行冲突处理规则配置。要使系统可以执行数据冲突处理,需要进行如下配置:

源端配置过滤器:

property = replicator.extractor.dbms.beforeColsFile=…/beforeColsRule.json

property = replicator.extractor.dbms.getBeforeCols=true

json配置:

{

"mytest.table_test1":"id",

"mytest.table_test2":"id"

}#用来进行比对的列,可以写多个,但是目标端只会用指定的哪一个,不是一定的是主键列

property = replicator.filter.bic.includeAllCols=true #配置此参数,json中不用写列名,默认全部列名(V2R2C3及之后)

目标端配置过滤器:

property = replicator.applier.dbms.conflictResolve=true

property = replicator.applier.dbms.beforeColsFile=…/conflictResolveRule.json

property = replicator.applier.dbms.optimizeRowEvents=false(v1r6C4之前必须配置,之后的版本可以不管)

property =replicator.applier.dbms.enable_handle_error=true(v1r6C4之前配置为false,之后的版本必须为true,否则事务冲突不生效)

conflictResolveRule.json配置:

{

"DEFAULT": "DISCARD", #此处支持DISCARD | OVERWRITE | IGNORE

#DISCARD 忽略并记录冲突sql,目标端不入库

# OVERWRITE 重写,将insert语句改为update然后入库

# IGNORE 忽略,就当做这个功能不存在,按照以前老逻辑处理,insert该报错就报错

"*test.tabl*": #模式名.表名 可以有通配符

{

"DETECTACTION":"UPDATE,DELETE", #insert冲突也必须写这两个

"COMPARECOLS":"id", #用来做比对的列,需要源端存并且是可是进行大小比对的列,可以是非主键列

"RESOLVERULE":

{

"INSERTROWEXISTS":"USEMINEQ:id", #insert冲突处理,可以选择这些规则USEMAX(col)|USEMAXEQ(col)|USEMIN(col)|USEMINEQ (col) | DISCARD | OVERWRITE | IGNORE

"UPDATEROWEXISTS":"USEMINEQ: id",

"UPDATEROWMISSING":"DISCARD",

"DELETEROWEXISTS":"DISCARD",

"DELETEROWMISSING":"DISCARD"

}

}

}

在apply()操作执行过程中,封装好的sql进行提交时,如果报错,系统会捕获异常,此时如果配置optimizeRowEvents=false,则系统会执行jdbcApplier类中applyOneRowChangePrepared()方法,该方法在捕获异常会根据异常类型执行conflictResolve()方法,该方法会读取配置文件中的异常处理规则,并生成异常处理规则实例conflictResolveRule,resolve()方法会通过getConflictType()方法获取冲突类型,以主键冲突INSERTROWEXISTS为例,系统会根据配置规则重构OneRowChange,匹配keySep和keyCloumn列,并将action由insert改为update,使源端冲突数据以更新的形式入库到目标端。

参考资料

KFS项目源代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值