具体业务细节不方便公开,但是这个问题警告我们在使用缓存的时候必须非常重视一致性问题。
首先来研究一下我们的缓存设计,我们选择了双机房双集群模式。也就是理论上说,每个机房都有一个独立的缓存集群,每次根据响应速度随机挑选一个比较快的集群访问,如果读取到数据,那么直接返回,如果没有读取到,那么从检查数据库并更新缓存记录。如果数据库里没有记录,那么先调用一个失效操作,然后写入缓存。整个系统看着没什么问题,但是天有不测风云~~~
现在看看我们的系统问题出在哪里,大胆假设,小心求证后,我发现我们的数据只写了缓存,并没有写到数据库记录。现在来还原案发现场:
集群A和B都没有记录。
集群A选中,没有记录,写入记录。
集群A选中,读取记录成功。
集群A选中,……
集群B选中,写入A中的记录读取不到(因为2个集群是相互独立的,而且我们只写缓存,所以没有从数据库读取更新缓存这一步),写入之前调用了一次失效操作,导致集群A的记录也失效,这时B集群记录写入。
集群B选中,读取记录成功。
集群B选中,……
集群A选中,第5步的情况又出现了。
每次状况5和8出现的时候,因为该读的缓存记录我们没有读取到,所以做了一个特定的操作。然后因为我们应用的访问量特别大,这个操作出现的次数也忒多了些,然后就悲剧了。
最后怎么解决的?代码一行没改,缓存配置为双机房单集群,只要记录写入了缓存就不存在两个机房不一致的问题。所以使用缓存,特别是分布式缓存,有没有持久化记录对于保证记录一致性的影响还是很重要的。
原文转自:http://blog.monstersay.cn/blog/2014/08/12/bug-cache/