如何高效安全的将资源同步到本地数据库

背景

       现在软件开发很多是多系统多模块,经常会遇到要将设备、人员、区域等资源同步到本系统数据库保存一份。资源同步常用的方案为全量同步和增量同步结合的方式,全量同步一般情况下为项目启动时和每天定时任务去同步所需资源,增量同步一般利用mq去接收资源的变更(增删改)通知然后修改到本地数据库。这里介绍下如何进行高效安全的全量同步。

全量同步

准备工作:
       假设要同步的表为region表,关键字段为(id, name, create_time, update_time),其他如(name, type, code)等根据业务而不同。另外创建一张region_temp表字段同region表。
调用其他系统的分页接口获取全量的region资源数据,并批量插入到region_temp表。
       region_temp表中已有最近同步的全量资源数据,但是,我们最终的目的是全量更新region表,针对以下场景分别阐述如何更新region表:

  1. 新增的数据
insert into region (id, name, code, create_time, update_time)
select t.id, t.name, t.code, t.create_time, t.update_time
from region_temp t
left join tb_region r on a.id = r.id
where r.id is null

       该SQL做的是将新增的数据插入到region表中。该SQL将region_temp表与region表左联接,左联接的结果再通过region表的id为空条件过滤记录,region_temp的数据较新,因此region_temp中存在而region中不存在的id必然是需要新增到region中的记录。

  1. 修改的数据
update tb_region  set name = m.name, code=m.code, create_time=m.create_time, update_time=m.update_time from
(select t.id as id ,t.name as name , t.code as code, t.create_time as create_time, t.update_time as update_time
from region_temp t inner join tb_region r on a.id = r.id and r.update_time < t.update_time) m
where region.id = m.t_id

       该SQL做的是将修改的数据修改到region表,其中,r.update_time < t.update_time的条件考虑到在做凌晨全量同步的过程中,可能发生了单条记录的更新操作(增量同步已经更新过了),因此,region表的update_time比region_temp表的update_time时间要早的记录才需要做批量的update操作,其余的以当前region表的记录为准。

  1. 删除的数据
update region set status = -1
 from
(select r.id as id
from region r left join region_temp t on t.id = r.id
where t.id is  null ) m
where region.id = m.id

       该SQL做的是删除region表需要删除的记录。该SQL将region_temp表与region表右联接,右联接的结果再通过region_temp表的id为空条件过滤记录,region_temp中不存在而region中存在的id,便是需要删除的记录。若是同步期间新增的记录,那么,再引入a.create_time <= ${sync_time},即小于等于触发同步操作的时间。

被筛选出来的需要删除的记录可以通过spring的event模型发送内部消息,通知其它模块删除了region表某条记录。

伪代码:

//先清空临时表再批量插入同步过来的数据
 baseMapper.deleteTemplateAll();
 baseMapper.insertBatch(regionList);
 //执行更新
 baseMapper.insertNew();
 baseMapper.updateChange();
 baseMapper.updateDelete();

       以上首先将数据保存到本地region_temp表,最后再在数据库层面进行region表的全量更新(不仅减少了和数据库传输的开销,而且更加高效)。若过程中出现获取全量资源失败,也不影响region表的正常crud,同时兼顾到删除的变更通知。另外,http全量获取资源的接口返回值中也不需要带上is_delete的软删除字段便可完成同步。

原文地址:https://www.cnblogs.com/seasail/p/12179354.html