赞
踩
如果数据不一致,那么业务应用从缓存中读取的数据就不是最新的数据,这会导致严重的错误
首先,我们必须知道这里的“数据一致性”是什么意思。这里“一致性”包括两种情况:
不符合这两种情况的,就是缓存和数据库的数据不一致了。
当缓存的读写模式不同时,缓存数据不一致发生的情况不一样。
对于读写缓存来说,如果要对数据进行增删改,就需要在缓存中进行,同时还要根据采取的写回策略,决定是否同步写回到数据库中。
所以,对于读写缓存来说,要想保证缓存和数据库中的数据一致,就要采用同步直写策略。不过,需要注意的是:如果采用这种策略,就需要保证同时更新缓存和数据库。所以,我们要在业务应用中使用事务机制,来保证缓存和数据库的更新具有原子性,也就是说,两者要不一起更新,要不都不更新,返回错误信息,进行重试。否则,我们就无法实现同步直接
当然,在有些场景下,我们对数据一致性的要求可能不是那么高,那么,我们可以使用异步写回策略。
对于只读缓存来说:
那么,这个过程中会不会出现数据不一致的情况呢?
(1)新增数据:
(2)删改数据
如果发生删改操作,应用既要更新数据库,也要在缓存中删除数据。这两个操作如果无法保证原子性,也就是说,要不都完成,要不都没完成,此时,就会出现数据不一致问题了。
具体的说,就是:
下图显示了先更新数据库,再删除缓存值时,如果缓存删除失败,再次重试后删除成功的情况
刚刚说的是在更新数据库和删除缓存值的过程中,其中一个操作失败的情况,实际上,即使这两个操作第一次执行时都没有失败,当有大量并发请求时,应用还是有可能读到不一致的数据
同样,我们按照不同的删除和更新顺序,分成两种情况来看。在这两种情况下,我们的解决方法也有所不同。
假设线程 A 删除缓存值后,还没有来得及更新数据库(比如说有网络延迟),线程 B 就开始读取数据了,那么这个时候,线程 B 会发现缓存缺失,就只能去数据库读取。这会带来两个问题:
怎么解决呢?在线程 A 更新完数据库值以后,我们可以让它先 sleep 一小段时间,再进行一次缓存删除操作。
redis.delKey(X)
db.update(X)
Thread.sleep(N)
redis.delKey(X)
(1)对于读写缓存来说,如果我们采用同写回策略,就可以保证缓存和数据库中的数据一致
(2)对于只读缓存
缓存和数据库的数据不一致一般是由两个原因导致的。其解决方案总结如下:
不过,当使用先更新数据库再删除缓存时,也有个地方需要注意,如果业务层要求必须读取一致的数据,那么,我们就需要在更新数据库时,先在 Redis 缓存客户端暂存并发读请求,等数据库更新完、缓存值删除后,再读取数据,从而保证数据一致性。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。