业务场景:地图绘制时将绘制好的地图信息(如坐标、关联任务信息等等)保存到DB同时在Redis中保存一份缓存数据。
问题描述:前端页面显示时发现有重复数据,如:同一个地图信息展示了两次。
解决思路:先是断点检查了一下代码,发现程序正常执行,检查DB物理数据库发现数据正常,检查Redis缓存数据发现将DB中的数据在Redis中存了两次。(DB*144条数据,Redis中288条数据)。
将Redis缓存数据清空,断点设置在Redis缓存数据保存处。发现同时有两次请求。
查找前端加载页面,发现jsp页面中的ajaxx同时加载了两次保存缓存数据的方法。
分析问题:开始以为是redis事物问题,于是开始添加Redis事物。 如:Transaction tx = jedis.multi(); 详细讲解博客:http://blog.csdn.net/s296850101/article/details/52416043
添加完Redis 事物后还是没解决问题,原因:即使添加事物,程序也是一条一条进入事物、保存数据、关闭事物。
仔细调试代码后发现是并发引起的,如下图:(原程序没有关键字synchronized) 在不加锁时,两条请求同时进入下图方法中,下图程序中的redis判断缓存Key是否存在的机制不起作用(如图中的第一个红框处)。第一个请求将144条数据放入Reids(调用rpush命令)
Redis Rpush 命令用于将一个或多个值插入到列表的尾部(最右边)。详细:http://www.runoob.com/redis/lists-rpush.html
如rpush解释的一样,第二调请求会将144条数据插入到第一个请求保存完的list后面,这样就出现了重复数据共288条。
解决办法,给方法加上synchronized锁。如下图。
解决问题过程中收集了几个博主的文章,有更好的见解或好的文章,欢迎留言:
https://www.cnblogs.com/danbing/p/5319820.html
http://blog.csdn.net/yangzhaomuma/article/details/51236976