线上问题描述
我们线上系统在会员注册后,立即查询会员信息,提示会员不存在,过了短暂时间查询又正常了,天哪噜呀,发生灵异事件了,这是什么原因,让我们来分析下吧!
问题分析
代码逻辑review
以下是伪代码,只为体现关注点,毕竟咱们也是有职业操守的^ - ^
@Transactional(rollbackFor = {Exception.class, RuntimeException.class})
public ResponseBean<RegisterAndBindResponse> registerAndBind(RegisterAndBindRO registerAndBindRO) {
MerchantMemberDO merchantMemebrInfo = merchantMemberService.getMerchantMemebrInfo(null, registerAndBindRO.getMobile(), registerAndBindRO.getMixMobile(), registerAndBindRO.getMerchantNum(), null);
//判断是否已入会
RegisterAndBindResponse registerAndBindResponse;
if (null == merchantMemebrInfo) {
//新增会员相关信息
registerAndBindResponse = brandMemberService.saveBrandMember(registerAndBindRO);
}
log.info("注册/绑定-共计耗时===>{}", sw.prettyPrint());
return ResponseBean.fromSuccessResult(registerAndBindResponse);
}
review代码的是因为,首先我们怀疑就是spring事务设置有问题,review过代码后排除了spring事务的原因,排除点总结如下:
- @Transactional(rollbackFor = {Exception.class, RuntimeException.class}) 系统中使用的是spring的事务注解,事务的传播机制(Propagation.REQUIRED)和事务隔离级别(Isolation.DEFAULT,默认使用数据库隔离级别)都是默认的,而且事务注解只在Facade方法上,Service层逻辑执行没有定义事务注解,
- 事务管理器也是spring默认的
数据库分析
基于以上的代码分析,使用spring事务托管,事务提交后数据库的数据肯定是插入完成,既然不是代码事务定义问题,那么问题就往下层推移,需要分析下数据库;
我司采购使用的是云数据库,阿里云的集群版polarDB,其技术架构如下:
分析如下:
- 从集群版polarDB架构图中可以看出,polarDB是分布式数据库解决方案,其采取了计算存储分离
- 看到架构图上面的读写分离几个字样就一下子打开了思路,如果是读写分析,那么是不是主节点和只读节点之前的同步时间差可能会造成刚插入的会员信息,立即读取可能存在读取不到的情况,
- 顺着以上的思路,我们找到了polarDB集群版的一致性特性和配置说明:
数据可靠性和一致性 数据库存储节点的数据采用多副本形式,确保数据的可靠性,并通过Parallel-Raft协议保证数据的一致性。
- 可以看到,数据一致性保证是分为3个级别,从最终一致性,会话一致性,全局一致性三个级别一致性保证是由低到高的,所以,如果一致性级别设置的是最终一致性和会话一致性,就可能出现上述问题
- 所以我们立即核实了我们polarDB的一致性级别配置,发现我们的数据库配置的级别就是最终一致性,所以是无法保证,主节点和只读节点之间数据同步很及时的。
解决方案
经过以上分析,我们找到了根本原因,但是如果要把一致性策略修改为全局一致性,虽然保证了一致性需求,但是这个级别的处理性能是最差了,考虑到会员注册场景我们既要保证数据一致性,又要保证接口的性能,我们需要寻求其他解决方案,通过查看polarDB的用户指南文档,我们找到了通过结合Hint语法修改注册核心逻辑的查询sql,在sql前加上/FORCE_MASTER/强制其走主节点查询,这样就可以保证注册逻辑中的数据一致性,也可以最大程度的保证接口性能。
至此,线上问题可以得到解决,在这次做此纪录,方便后续遇到类似问题,大家可以模仿此类思路,遇到数据一致性问题无非就是从代码逻辑,事务,或者数据库引擎策略几个方面去排查,天下没有无端的bug,只需静心分析而已。
参考文档:
阿里云polarDB官方产品文档:
https://help.aliyun.com/document_detail/58609.html?spm=a2c4g.183258.0.0.26c13c0f2eckR5
一致性级别说明文档:
https://help.aliyun.com/document_detail/99093.htm?spm=a2c4g.119094.0.0.58e27c41nGOqAR#concept-vvz-lzg-1gb
Hint语法说明文档:
https://help.aliyun.com/document_detail/477438.html?spm=a2c4g.85143.0.0.23431a2eFoYXND
阿里云polarDB FAQ文档:
https://help.aliyun.com/document_detail/119094.html