92、先比较,再更新,速度极快

本文探讨了系统间数据同步的问题,包括数据库同步和向Elasticsearch(ES)写入数据的常见方法。提出了先比较后更新的优化策略,避免全量删除和重建,以提高效率并减少对其他系统的影响。同时,给出了Java代码示例,展示如何实现差异比较和更新操作。
摘要由CSDN通过智能技术生成

一、问题

一个系统,经常需要和上下游同步数据,比如账务dts从crm同步客户数据,新dts从老dts同步用户数据,ehr需要把xx数据写进redis。

二、常见的办法

1、数据库之间的同步

先删除所有数据,再保存所有数据;整体作为一个事务。

问题:速度很慢。如果表的id被其它业务关联了,也不方便。

更好的办法:先从系统的数据库表,查询存在的数据;和需要同步查询的数据作比较, 判断哪些是新增的、哪些是删除的、哪些是修改的。

即:先比较再更新。

2、向es写数据

最差的办法:删除所有数据,重建索引。xx就这么干过?

一般的办法:直接调用es的接口,为所有数据,重建索引。大概有个index方法,传入数据。

更好的办法:先从es查询数据,和数据库的数据做比较,如果变化了,才有必要更新es的数据。

三、初步分析

1、系统的数据变化,通常没有那么多,那么频繁

2、数据库、es的修改删除等操作,尤其是带了事务,会非常慢;而查询是极快的

3、频繁操作数据库,不但自己的系统慢,可能还影响到系统内的相关模块的db访问速度,影响到数据库相关的其它系统服务。

四、代码示例

import java.util.List;

import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import com.google.common.collect.Lists;

@Service

public class AuthUserService extends MpServiceImpl<AuthUserMapper, AuthUser> {

    @Autowired

    private OldAuthUserMapper oldAuthUserMapper;

    // 返回变化的

    public Integer sync() {

        Wrapper<OldAuthUser> queryWrapper = Wrappers.query();

        List<OldAuthUser> oldList = oldAuthUserMapper.selectList(queryWrapper);

        AuthUser query = new AuthUser();

        query.setIsDeleted(YnEnum.NO.getCode());

        List<AuthUser> dbList = super.list(query);

        Map<Integer, AuthUser> dbUserMap = ListKit.listToMap(dbList, AuthUser::getOldId);

        List<AuthUser> changedList = Lists.newArrayList();

        for (OldAuthUser oldAuthUser : oldList) {

            try {

                one(dbUserMap, changedList, oldAuthUser);

            catch (Exception e) {

                log.error("AuthUserService sync error", e);

            }

        }

        return changedList.size();

    }

    private void one(Map<Integer, AuthUser> dbUserMap, List<AuthUser> newList, OldAuthUser oldAuthUser) {

        Integer oldId = oldAuthUser.getId();

        AuthUser dbUser = dbUserMap.get(oldId);

        if (dbUser != null) {

            boolean changed = changed(oldAuthUser, dbUser);

            if (changed) {

                AuthUser newDbUser = newDbUser(oldAuthUser, dbUser);

                newList.add(newDbUser);

                super.updateById(newDbUser);

            }

        else {

            AuthUser saveDbUser = saveDbUser(oldAuthUser);

            newList.add(saveDbUser);

            super.save(saveDbUser);

        }

    }

    private AuthUser newDbUser(OldAuthUser oldAuthUser, AuthUser dbUser) {

        AuthUser newDbUser = BeanKit.build(oldAuthUser, AuthUser.class);

        newDbUser.setId(dbUser.getId());

        newDbUser.setUpdateTime(DateKit.now());

        return newDbUser;

    }

    private static boolean changed(OldAuthUser oldAuthUser, AuthUser dbUser) {

        // str

        if (StringKit.notEquals(oldAuthUser.getUsername(), dbUser.getUsername())) {

            return true;

        }

        if (StringKit.notEquals(oldAuthUser.getPassword(), dbUser.getPassword())) {

            return true;

        }

        if (StringKit.notEquals(oldAuthUser.getLastName(), dbUser.getLastName())) {

            return true;

        }

        if (StringKit.notEquals(oldAuthUser.getFirstName(), dbUser.getFirstName())) {

            return true;

        }

        if (StringKit.notEquals(oldAuthUser.getEmail(), dbUser.getEmail())) {

            return true;

        }

        // int

        if (EqualsKit.notEquals(oldAuthUser.getIsActive(), dbUser.getIsActive())) {

            return true;

        }

        if (EqualsKit.notEquals(oldAuthUser.getIsStaff(), dbUser.getIsStaff())) {

            return true;

        }

        if (EqualsKit.notEquals(oldAuthUser.getIsSuperuser(), dbUser.getIsSuperuser())) {

            return true;

        }

        // date

        if (EqualsKit.notEquals(oldAuthUser.getDateJoined(), dbUser.getDateJoined())) {

            return true;

        }

        if (EqualsKit.notEquals(oldAuthUser.getLastLogin(), dbUser.getLastLogin())) {

            return true;

        }

        return false;

    }

    private AuthUser saveDbUser(OldAuthUser oldAuthUser) {

        AuthUser authUser = BeanKit.build(oldAuthUser, AuthUser.class);

        authUser.setId(null);

        authUser.setOldId(oldAuthUser.getId());

        authUser.setCreateTime(DateKit.now());

        authUser.setUpdateTime(DateKit.now());

        authUser.setIsDeleted(YnEnum.NO.getCode());

        return authUser;

    }

     

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值