zoukankan      html  css  js  c++  java
  • 如何高效安全的将资源同步到本地数据库

    背景

           现在软件开发很多是多系统多模块,经常会遇到要将设备、人员、区域等资源同步到本系统数据库保存一份。资源同步常用的方案为全量同步和增量同步结合的方式,全量同步一般情况下为项目启动时和每天定时任务去同步所需资源,增量同步一般利用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的软删除字段便可完成同步。

  • 相关阅读:
    获取项目中.txt 文件的内容
    jdbc 连接各种数据库
    修改Eclipse中项目在Apache Tomcat中的部署路径
    java学习之继承之子父类中变量的特点
    java学习之继承、多态
    java学习之单例模式(饿汉式与懒汉式)
    java学习之对象初始化过程
    java学习之静态块、显示初始化块、构造函数、this在构造函数中的调用,区别联系与调用顺序
    java学习之数组的两种常见错误
    java学习之堆与栈的区别
  • 原文地址:https://www.cnblogs.com/seasail/p/12179354.html
Copyright © 2011-2022 走看看