欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > 文章正文

开发数据同步服务时容易犯的错误,然而,开发者有时会忽

来源: javaer 分享于  点击 14355 次 点评:28

开发数据同步服务时容易犯的错误,然而,开发者有时会忽


未判断是否成功获取数据就进行下一步操作

问题描述

在同步服务中,数据的获取通常是第一步,例如从数据库、API 或其他数据源中拉取数据。然而,开发者有时会忽略对获取数据的有效性进行检查,直接进入下一步操作(如更新数据或删除旧数据)。如果数据获取失败或返回空值,可能会导致后续操作异常,甚至引发数据丢失或系统崩溃。

典型案例1:同步海康视频列表

一个定时 job 需要每天从海康远程 API 获取视频列表数据,然后更新本地数据库。如果未检查 API 返回的数据是否为空或是否符合预期格式,可能会导致以下问题:

  • 如果 API 返回空数据,程序可能尝试更新一个空对象,导致数据库中数据被覆盖为空。
  • 如果 API 返回异常数据(如格式错误),程序可能抛出异常,影响同步流程。

具体代码

        log.info("开头同步海康数据");
        ArtemisConfig artemisConfig = GetArtemisConfigInfoConfigByKey();  //读取配置 hikconfig
        HikRequest hikRequest = new HikRequest();
        String first = hikRequest.SendCameras(1, 10, artemisConfig);
        //log.info("获取总数据的内容是"+first); 
        JSONObject jsonObject = JSON.parseObject(first);
        String code = jsonObject.getString("code");
        if (code.equals("0")) {//判断能获取数据 
             //log.info("获取总数据成功");
            JSONObject data = jsonObject.getJSONObject("data");  
            Integer total = data.getInteger("total");
            log.info("获取总数据是"+total);
            Integer pageSize = 1000;
            Integer totalPage = (total + pageSize - 1) / pageSize;
            Integer pageNo = 1;
            String connStr = param;
            DataTemplate postgresqlDataTemplate = DatabaseUtil.getDataTemplate(DataSourceType.POSTGRESQL.toString(),
                    connStr
            );
            while (pageNo <= totalPage) {
                log.info("开始" + pageNo + "页");
                String result = hikRequest.SendCameras(pageNo, pageSize, artemisConfig);
                //log.info("获取数据内容是"+result);
                List<Map<String, Object>> maps = hikRequest.GetCameraList(result);
                if (!maps.isEmpty()) {
                    log.info("获取" + maps.size() + "条数据");
                    hikRequest.SaveCameraList(maps, postgresqlDataTemplate);
                    pageNo++;
                } else {
                    log.info("获取 0条数据");
                    break;
                }
            }
            //删除更新时间是前天的数据;
            LocalDate yesterday = LocalDate.now().minusDays(30);
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            String formattedDate = yesterday.format(formatter);
            String sql = "delete from hik_camera where data_update_time < '" + formattedDate + "';";
            postgresqlDataTemplate.execute(sql);
            //postgresqlDataTemplate.execute("ANALYZE VERBOSE hik_camera; "); 
            //视频 卡口 人像 统计摄像头数量
            statisticCamera(postgresqlDataTemplate);
            log.info("海康摄像头统计数据表 hik_camera_statistic 更新成功");
            postgresqlDataTemplate.close();
        }
        return "OK";
    }

致命问题

具体流程如下:

  1. 获取数据总页数。
  2. 分页获取更新数据。
  3. 删除旧数据。

然而,之前的实现存在问题:

  • 未对“分页获取更新数据”是否成功进行判断,就直接执行“删除旧数据”的操作。
  • 在现成环境中,如果设置分页大小为 10000,对方接口会报错,导致更新视频数据失败。
  • 由于未检查更新数据是否成功,程序继续执行删除旧数据的操作,最终导致数据库表中的数据被清空。

典型案例2:MySql中的数据同步到PG数据库

在进行数据同步的同时,没有考虑到数据是否有获取同步到对应的数据库,就进行了数据的删除。

总结

在同步服务中,数据获取的有效性检查是至关重要的环节。未进行充分的检查可能导致数据丢失、系统异常等问题。通过加强异常处理、事务管理以及日志监控,可以有效降低风险,确保同步流程的稳定性和数据一致性。

相关栏目:

用户点评