• Java代码实现两个数据库之间的数据同步


    需求背景

    有A&B两个数据库,以A为主,B要同步A上的数据,同步涉及数据的增删改查,且要每天同步一次。条件限制是,只能调用中台提供的接口操作数据库,不能写SQL。

    解决思路

    由于只能通过中台调用接口操作数据库,所以解决方法被限制在后端代码层面。至于每天执行一次,使用SpringBoot的定时任务注解@Scheduled就可以了。
    最好的解决思路写在最后。

    1 遍历遍历再遍历

    对于增加和修改,将A库中所有的数据通过接口拿到一个List里面,遍历这个List,每一趟检查B库中是否存在主键对应的数据,如果存在,则将数据更新,如果不存在,则直接插入。
    对于A库中删除的数据,需要反向遍历,即将B库的数据拿出来,将数据进行遍历对比,如果发现B库中有的数据而A库中没有,则删除B库中的数据。
    可以看到这个方案需要不停的遍历,效率很低。

    2 B中数据全删了,把A中的数据写上

    如题,通过中台拿到A中的数据,然后把B库清空,再写A库的数据。
    逻辑十分简单,但清空数据库很吓人也会导致很多问题,非常不优雅。

    3 内存中对比变化,只把变化落盘到数据库

    大致思路是通过数据中台拿到A库的List和B库的List,比对这两个List的差别,只把差别写到数据库。
    将A库中的数据拿到newList中,B库中的数据拿到oldList中,对newList进行遍历,每次遍历都寻找oldList中是否存在与newList对应的数据(通过主键作为对应标识);如果存在,则判断两个对象是否相等(要重写equals()和hashcode()方法),相等则直接从两个队列中剔除这个数据,不相等则调用接口进行数据更新,更新完了之后将更新过的数据从两个List中剔除;这样遍历完了之后,newList中剩下的没被剔除的数据就是B库需要新增的数据,oldList中剩下的没被剔除的数据就是B库需要删除的数据,需要修改的数据在遍历过程中已完成修改。
    由于比对操作是在内存中完成的,所以这个方案的性能比前两个要高不少,十分优雅。
    这个方案的伪码如下:

    //A库中的数据同步到B库伪码
    
    //A库中的数据拿到newList中,B库中的数据拿到oldList
    List<Data> newDataList;
    List<Data> oldDataList;
    
    //从数据库中取数据......
    
    //开始遍历比对
    for (Data newData : newDataList) {
    	for (Data oldData : oldDataList) {
    		//通过主键判断oldData与newData是否为同一条记录(对应)
    		if (newData.getId().equals(oldData.getId())) {
    			//主键对应上了,下面判断数据是否发生更改
    			if (!newData.equals(oldData)) {
    				//新旧数据不同,发生了更改,将更改落盘到数据库
    				dataService.updateData(newData);
    			} else {
    				//新旧数据一致,说明没有发生更改,什么也不做
    			}
    			//新旧数据比对并操作后,将这两个数据从List中“移除”
    			newData = null;
    			oldData = null;
    		}
    		//两个数据主键没有对应上,说明不为同一条记录,继续遍历
    	}
    	//遍历完成之后,如果新数据在旧数据中有主键对应,则肯定会被置null
    	//没被置null说明这条新数据是新增的,需要调用接口落盘
    	if (newData != null) {
    		dataService.insertData(newData);
    	}
    }
    
    //遍历完新数据后,oldDataList中剩下的没被置null的都是需要删除的
    for (Data oldData : oldDataList) {
    	if (oldData != null) {
    		dataService.deleteDataById(oldData.getId());
    	}
    }
    
    //此时新旧数据库的内容就同步成一样的了
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
  • 相关阅读:
    如何测试生成式人工智能(AIGC)
    Spring学习之注解@Autowired、@Qualifier、@Resource
    Reactor网络模式
    Django中序列化器or模型单独使用
    【Maven】Maven快速入门2022版:从概念、安装到基本使用
    ES6 入门教程 3 变量的解构赋值 3.2 对象的解构赋值
    快鲸scrm系统:解决企业管理的三大核心痛点问题
    java中批量导出文件并压缩到zip文件中
    在Docker中运行Jenkins容器:从入门到实践
    hdlbits系列verilog解答(模块按位置)-21
  • 原文地址:https://blog.csdn.net/kitahiragawa/article/details/125980214