Redis缓存在现在的项目中应用越来越广泛,几乎大部分项目中都会用到,从简单的存储登录时的短信验证码到大量数据的缓存,由此可见,Redis已经是广大开发者常用的缓存工具了。那么在特殊的场景下,需要严格保证缓存与数据库的数据一致,那么这时候需要如何做才能保证呢?
一、不严格要求一致性的情况下,利用缓存的场景下。先查询缓存,如果缓存有数据,则直接返回;如果缓存没有数据,则先查询数据库,获取到数据后再将数据放入缓存中,以供下次查询。如果数据改变了,则立刻更新缓存。
二、在严格要求一致性的情况下,大约有以下三种场景(策略):
- 先更新数据库,再更新缓存
- 先删除缓存,再更新数据库
- 先更新数据库,再删除缓存
1、先更新数据库,再更新缓存。
在高并发的场景下,这种策略会有很大的问题,比如AB两个请求同时更新数据,A更新完数据,在更新缓存前,B先完成了更新数据库和缓存,此时A再更新缓存,那么数据就出错了。(这种方式不建议使用,无论是不是高并发场景下)
2、先删除缓存,再更新数据库。
在高并发的场景下,这种策略也会有很大的问题,比如AB两个请求,A先删除缓存,再更新数据库,当A删除完缓存,还没来得及更新数据库,此时B请求查询,发现缓存被删除了,所以直接查询数据库旧的数据并更新到缓存,当B操作完成了,A才完成数据库更新,那么此时数据库数据和缓存数据不一致了。
如果对这种方法进行改进,还是勉强可以使用的,如何改进呢?如下:
(1)先删除缓存。
(2)再写数据库(这两步和原来一样)。
(3)休眠n秒,再次删除缓存,等待下次查询刷新缓存(多了这一步)。
这种改进方式,只能适合单机并且删除缓存成功的情况下。如果更新数据库后删除缓存失败了,那么还是会出现不一致的问题。
3、先更新数据库,再删除缓存。
一般情况下,先更新数据库再删除缓存,一样会出现缓存删除失败的情况。这是为了确保缓存删除成功,需要额外去借助消息队列去完成删除缓存,只要缓存删除失败就重试,直到成功。步骤如下:
(1)、更新数据库。
(2)、删除缓存,如果删除失败,将缓存key发送至消息队列,队列消费实现删除缓存操作。
三、总结
缓存一致性需要考虑的东西很多,需要根据自己项目的并发场景和实际情况去选择,如果是简单的缓存,那就没必要去实现那么复杂的东西,以上只是自己个人的总结,如果错误,望指正。