问题复现
今天加班写了一个接口,刚开始发现诶数据还是正常的,觉得可以上线了,因为这个接口只是去ES查了一次数据,统计了一下数量,前端验证也没什么问题,但是突然,我发现了另一个问题:
这里面待处理是0 啊,为什么接口返回的是10,有值导致前端加了一个小红点,代表有会话的。
然后我就去看我写的代码
问题出在SQL查询,因为我要查询这个组(你可以理解为一个小组)下的所有数据。结果我没剔除已经删除了的人(账户).结果把那些剔除出这个组的账户的会话也查询了出来。
那好啊,我直接把SQL改了就行了吧,只查离线,在线的,那些删除的我不查这样总行了吧
结果,想象是美好的,现实是残酷的,还是数据不对,这个地方还是10,10
那是什么问题?
出路
因为这个地方是去查ES的,我在MySQL肯定是查不到这个结果的,难道是因为ES和MySQL数据不同步的原因么?
然后我就去ES查询工具查了一下,发现没有数据啊,都是0,应该也是两个0的,那么肯定就是代码问题了,然后我就回头开始看代码流程,最后发现,原因是我查询这个组的用户/账户后,并没有判空/null操作,就像MyBatisPlus一样,如果传递的参数为null,他会自动把这个参数给去掉,就是像这样
那是不是说我链接ES然后去查询的时候,ES看到这个参数传递的是null,他也把这个查询条件给干掉了,经过验证,确实是这样,ES的机制跟MyBatisPlus,或者上面那种SQL的写法一样,他也会帮你做一次判断,至此问题排查出来
解决
这个bug很简单,只是当时并没有想到这种情况,解决办法就是如果我查询的这个组下面的用户集合是个null的话,我们直接return就行了,return 这个对象都是0就行了
扩展延伸
如果在ES中使用了Agg聚合查询,有可能会出现聚合查询的结果不准确,会出现一些不是你想要的结果。那有可能是因为你的分片数较多,分片多了导致聚合查询的时候不准确,这个就是聚合准确性的一个优化了,每次聚合查询Kibana都会返回两个参数,如下
"aggregations" : {
"dest" : {
"doc_count_error_upper_bound" : 52, 最大错误数
"sum_other_doc_count" : 3187, 总错误数
"buckets" : [
要想优化:要么我们数据量小一点,将主分片设置为1,要么我们查询的时候携带上参数shard_size。让这个值尽量的大一点,这样就可以减小误差,当doc_count_error_upper_bound返回值为0的时候,就说明我们的结果精确了