前言
之前负责的一个项目上线好久了,最近突然爆出一 Bug,最后评估影响范围将 Bug 升级成了故障,只因为影响的数据量有 10000 条左右,对业务方造成了一定的影响。
但因为不涉及到资金损失,Bug 修复后对数据进行修补,所以最终级别也是较低的。
今天和大家分享这个线上隐匿的 Bug,也好在工作的项目中得以借鉴哈~
需求背景
主题:民宿入住回访问卷
描述:
针对入住民宿的顾客,在离店后的当天或第二天内需要给顾客发送本次入住民宿的回访问卷,以此收集顾客入住体验的意见或建议
说明:
因为数据量较大,采用的是 Hive 库存储数据和逻辑加工
问题分析
1.业务逻辑
**t2表:**存储(昨日+今日此时)离店的顾客清单信息
**t3表:**存储已发送过回访问卷的顾客清单信息
出现 Bug 的核心业务逻辑如下:
所使用的等值关联字段为:
t2.id = t3.primary_id
从t2表
中过滤掉t3表
中的数据,通过使用t2表
作为主表left join
子表t3表
然后判断t3.primary_id is null
,说明是没有发送过的。
2.问题出现
t2.id
字段类型为:string 类型
t3.primary_id
字段类型为:bigint 类型
两个不同类型的字段进行等值关联时,当t3.primary_id
实际值为超过 16 位的数值时则在 MapReduce 计算过程中将其字段类型由 bigint 类型转换为 double 类型,此时就出现了精度缺失的情况。
例如:
# 此处只是用来举例说明问题,不代表实际真实值
t2.id = 1000110000000000
t3.primary_id = 10001100000000009
- 1
- 2
- 3
如上例子,t3表
中已有 primary_id = 10001100000000009
的记录发送过回访问卷
此时t3.primary_id = 10001100000000009
的值超过 16 位,将其转换成 double 类型时,将其值进行截断后再等值关联
则会出现将t3.primary_id = 1000110000000000
(将末尾的9去掉)再与t2表
中的id
关联
正好关联上已有 primary_id = 10001100000000009
的记录,所以认为此条记录不应该再发送回访问卷,直接被过滤掉了
而实际业务中这条记录并不在已发送回访问卷记录表中,只因为精度缺失导致不该关联上的两条记录再被截断后错误的关联上了
结果:导致应该发送回访问卷的顾客,没有被发送
解决方案
1.Bug 解决
当时线上出现这个 Bug 后第一时间的解决方案是:
将等值关联的字段进行类型转换,全部转换成 string 类型后再进行等值关联
使用cast函数
进行类型转换,这样可以解决精度缺失的问题
2.漏掉数据处理
将等值关联处修改后的代码逻辑,按照影响的业务数据时间范围,重新执行一次,找出本应该发送回访问卷但因此 Bug 而未发送的顾客清单,发送一次回访问卷。
总结
通过前面的分析,可看出这个线上的 Bug 比较隐匿,如果对隐式转换规则不清楚,则很大可能会出现这方面的问题。
今天给大家分享这个隐式转换的 Bug,希望在今后的工作项目中有类似问题时可借鉴一二。
除了出现 Bug 后的补救措施,在以后的项目中我们能提前做些什么呢?
- 一旦出现等值关联,则需要考虑关联字段的字段类型是否一致;
- 定义表时,需要结合具体业务情况考虑可能出现的最大值的数据范围;
- 不能因为害怕出现此问题,在不加思索的情况下,只要等值关联就使用
cast函数
进行 string 类型的转换;
欢迎关注 无量测试之道
公众号,回复领取资源
Python+Unittest框架API自动化、
Python+Unittest框架API自动化、
Python+Pytest框架API自动化、
Python+Pandas+Pyecharts大数据分析、
Python+Selenium框架Web的UI自动化、
Python+Appium框架APP的UI自动化、
Python编程学习资源干货、
Vue前端组件化框架开发、
资源和代码 免费送啦~
备注:我的个人公众号已正式开通,致力于IT互联网技术的分享。
包含:数据分析、大数据、机器学习、测试开发、API接口自动化、测试运维、UI自动化、性能测试、代码检测、编程技术等。
微信搜索公众号:无量测试之道
添加关注,让我们一起共同成长!
</article>