问题描述
在处理业务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。