问题描述
在处理业务json数据时,将数据存入对象集合后再进行新增到数据库导致数据库数据重复。更奇怪的是测试环境不会出现此种重复数据情况,重复数据也只出现再生产环境。
StringBuffer buffer = new StringBuffer(); buffer.append("addUser"); buffer.append(Constants.colonSeparate); buffer.append("userId"); buffer.append(Constants.colonSeparate); buffer.append(userId); try { if (RedisUtils.getLock(redisClient, buffer.toString(), "")) { isOrder = true; JSONArray dataArr = JSONArray.parseArray(json); List<User> userList = new ArrayList<>(); for(Object obj : dataArr) { JSONObject dataObj = JSONObject.parseObject(obj.toString()); final String name = dataObj.getString("name"); JSONArray agrArr = JSONArray.parseArray(dataObj.getString("ageList")); for (Object agrObj : agrArr) { JSONObject showObj = JSONObject.parseObject(agrObj.toString()); Long age = showObj.getLongValue("age"); User user = new User(name,String.valueOf(age)); //去重保存数据 List<User> users = userList.stream().filter(e -> name.equals(e.getName())) .filter(e -> String.valueOf(age).equals(e.getAge())).collect(Collectors.toList()); if(StringUtils.isListEmpty(users)){ userList.add(user); } } } //新增数据 userList.forEach(user -> userDao.save(user)); } else { throw new APIException("操作频繁,请稍后再试!"); } }finally { if (isOrder) { RedisUtils.releaseLock(redisClient, buffer.toString()); } }
原因分析:
1.并发
因为在业务执行前还做了清除,故可能存在前一条请求数据还未执行完成,后一条请求数据又执行进来了。于是增加了redis分布式锁,观察一段时间后,发现依然有重复数据追加到数据库中。
2.json数据内容重复
在初始代码中是并验证过滤需要保存的数据,故存在json中可能有重复内容存在,于是就有了图中去重代码。但可惜的是并没有解决重复数据追加问题。
3.stream()中的filter并没有真正过滤掉json中的重复数据
在无计可施的时候抱着这种猜测,将对象集合换成Map,Map中存储的是json解析的数据,解析完后再将数据新增到数据库。于是奇迹发生了,数据不在出现重复数据。至于具体为什么不会再出现这种情况未知。
解决方案:
1.增加redis分布式锁
2.过滤重复数据
3.将对象集合替换成Map。