一、问题
今天线上的数据透出的时候突然出现了一些莫名其妙的数据,导致前端页面出现很多的数据找不到的问题。
1 | [ |
数据是否一致? 但是很奇怪的是,预发(正式测试环境)的数据是好的,而只有线上的数据是坏的,于是首先想到的是线上跟预发的数据是不是不一样?
失望的是,预发跟线上的不管是DB、搜索引擎以及kvstore等等数据存储方式的数据都是同一套,不可能存在预发跟线上数据不一致的情况。
数据处理是否区分环境 既然排查了数据不一致的问题,那么接下来只能看代码里面有没有对数据的获取来源、处理来源等等数据处理或者获取方式可能存在问题,是否区分环境。
于是只能查看代码了,因为接手应用不久,应用的代码也经过了很多的修改,而且每个对外透出的数据居然都是Map的方式,找起来异常的艰难。
是否有环境处理开关 终于找到了几个开关,在metabaseyou进行数据配置,因为metabase是环境隔离的,在预发以及线上进行配置的diff,终于发现是一个开关不一样,预发是关闭的,而线上是开启的,而这个开关是用来判断是否开启缓存的,为了解决问题,直接把预发的数据同步到线上。
二、解决方式
但是到现在还是没有找到为什么会出现,“$ref”: “$[1]”这种奇怪的透出数据,看到ref第一反应是引用,会不会是引用有问题呢?
那数据添加进返回的Map是正常的,会不会是序列化问题呢?于是翻看 FastJSON的wiki,发现官方的解释如下:fastjson文档
看到官方文档,再看看我的返回数据,一切就像拨开云雾见月明的感觉,从文档可以看到,问题的出现是因为我们有相同的数据,奇怪的“$ref”: “$[1]”代表的意思是,此处取到的数据是这个列表的第一个数据同一个,它是一个引用,指向了第一个数据。而fastjson序列化的时候有很多的序列化方式,如果需要避免出现重复引用,序列化应该选择SerializerFeature.DisableCircularReferenceDetect序列化方式,该种方式可以解决循环引用的问题,而默认是不开启的,所以会出现上图的问题。
另外的一种方式是:BeanUtils.copyProperties(oldobject, newobject);改成对象新对象拷贝旧对象信息,将新对象存入列表的方式也可以解决问题。
使用这两种方式之后,数据也正常了,如下所示:
1 | [ |
三、测试代码
1 | /** |