自定义Session共享导致的问题排查
记一次Session共享导致的问题,底层代码自定义了分布式session共享,在以往都是正常的,但在前段时间突然出问题了,出现了数据不致,因为使用的redis主从进行的session共享,首先怀疑数据未及时同步,排查后发现数据已经同步到各从库。
再次分析报错日志,发现出现数据一致性问题时都是在两台web服务器间切换时发生。继续与前端确认,前端所有请求均是异步请求。分析服务端代码,发现session共享时存在二级缓存session,一级session是servlet创建生成的,通过cookie中sessionId获取,且sessionId只有第一次创建时才会返回;二级是自定义的globalSession,通过cookie中gsessionId获取。逻辑中当存在sessionId且可以根据sessionId获得session时不会获取redis中的globalSession,否则获取redis中缓存的globalSession。
重点来了,假设:现在有A、B两台服务器,当前sessionId指的是A中一级session,异步请求时,多个接口发到服务端的sessionId是相同的,当一个更新接口与一个查询接口异步发送时。
1、更新请求异步发送到了A,导致globalSession变更,redis中缓存更新;
2、查询请求异步发送到了B,由于sessionId不匹配,导致B创建了一级session,在返回数据后将cookie中sessionId覆盖;
3、查询完成后,更新请求处理完后返回,由于更新请求发送时sessionId命中,导致返回数据中cookie为空,sessionId未被覆盖,这时cookie中sessionId指向B;
4、发送下一个请求,如果这时发送到了B,由于sessionId可以拿到session,导致并未创建session,因此并未获取redis中的最新globalSession,导致数据不一致。
找到原因了,解决方法就很简单了,只要让多次请求到达同一个服务器即可,ip-hash就可行,当然这回导致负载均衡的问题,但别忘了网关。