最近负责的系统总是出现奇怪的缓存问题,在这里简单记录一下碰到的问题和踩到的坑。
问题:用户反映使用不同账号A,B登录时,都出现账号A的页面信息(未邮寄账单提示)。如下所示:
图1:未邮寄账单提示一 session缓存问题
鉴于之前也出现过类似的session缓存问题,session的key信息未清除。
如果A用户切换至B用户时,使用了不同的session key如‘U’,‘U_P’保存不同的信息,但是切换后只清除了'U'信息,忘记清除'U_P'信息,则可能导致A用户和B用户看到同样的‘U_P’信息。查看此处的代码也确实使用了seesion缓存:
图2:未邮寄账单session缓存是不是这个原因引起的呢,之前的这个问题按说已经修复了,难道还有啥代码没改?查看代码,切换用户的时候移除了session的内容,登出账号的时候也失效掉了session信息。
图3:session清除通过查看后台服务器日志,发现A用户登录后调用了/un-post-billls-GET链接,获取到了未邮寄账单信息。但是B用户的后台日志没有找到调用过后台的链接,所以排除了后台session缓存错误的可能。后台日志就不上图了,^_^。
二 浏览器本地缓存问题
由于B用户根本就没有调用后台服务,就拿到了未邮寄账单的信息,我们认为很大可能是浏览器本地缓存引起的问题。
1 Localstorage缓存
查看前端代码,在查询未邮寄账单信息时,使用了HTML5的window.localStorage来保存用户的信息,代码如下:
图4:localstorage缓存并没有看到对localStorage的clear操作,这样可能是有问题的:A用户登录后在localstorage保存了未邮寄账单信息,切换至B用户后由于没有clear A用户的localstorage 信息。那么B用户就看到了A用户的本地缓存信息。
解决办法:在合适的时机清理localstorage,使用不同的key 保存缓存信息。
2 浏览器url缓存
这个bug是否就这样解决了呢?仔细看图4的localstorage代码,A用户和B用户实际上使用了不同的dataKey_A与dataKey_B来保存各自的localStorage,虽然说有一定的安全问题,但是由于不同的KEY存在,按道理说B用户不会看到A用户的未邮寄账单信息。问题可能不在localStorage这里。
根据 HTTP 规范,GET 用于信息获取,而且应该是幂等的。也就是说,当使用相同的URL重复GET请求会返回预期的相同结果。这个问题与现在的情况非常相似。
查看代码,使用了相同的URL请求重复GET:
图5:URL请求GET解决办法:
1. GET请求URL后加随机数,让服务器认为不是相同的请求。
例 “/un-post-bills?t=” + new Date().getTime()
2. 使用POST代替GET,浏览器不会对POST做缓存
三 总结
WEB系统的缓存通常有好几级,本地缓存,服务器缓存,数据库缓存等。分析缓存问题时,要考虑每一层可能引起的问题,每一层的缓存技术也有很多种,要根据具体的场景来选择使用何种缓存技术。
缓存技术博大精深,本文只记录寻找bug时涉及的技术,其他有待学习。
网友评论