阜新本地网站建设平台,如何制作微视频宣传片,中装建设是做什么的,网上推广营销前言
日常开发中常会使用redis作为项目中的缓存#xff0c;只要我们使用 Redis 缓存#xff0c;就必然会面对缓存和数据库间的一致性保证问题。而且如果数据不一致#xff0c;那么应用从缓存中读取的数据就不是最新数据#xff0c;可能会导致严重的业务问题。
为什么会数…前言
日常开发中常会使用redis作为项目中的缓存只要我们使用 Redis 缓存就必然会面对缓存和数据库间的一致性保证问题。而且如果数据不一致那么应用从缓存中读取的数据就不是最新数据可能会导致严重的业务问题。
为什么会数据不一致
数据一致性指的是redis缓存跟数据库的数据的一致。假如缓存中没有数据那么数据库的值必须是最新的。如果缓存中有数据那么缓存中的值需要跟数据库的值相同。
理解完上述数据一致性的前提我们看下什么情况下会导致缓存跟数据库的数据不一致。
并发更新问题当多个客户端同时对同一个数据进行更新时假设有两个客户端同时读取了数据库中的数据然后对其进行了修改并分别将修改后的数据存入缓存。因为两个客户端并不知道对方的修改所以会导致缓存中存储的数据和数据库中的数据不一致。异常情况在更新缓存的过程中如果发生了错误或者异常可能导致缓存更新失败从而导致缓存和数据库数据不一致大致分为如下两种场景。
场景问题先删除缓存再更新数据库先删除缓存值 数据库更新失败导致请求再次访问缓存时发现缓存缺失再读数据库时从数据库中读到旧值先更新数据库再删除缓存缓存删除失败导致请求再次访问缓存时发现缓存命中并从缓存中读取到旧值
如何解决数据不一致的问题
无论是先操作缓存还是先操作数据库假如后者执行失败我们可以发起重试尽可能地去做「补偿」。我们可以把要更新/删除的值暂存到消息队列中当应用没有能够成功地更新/删除数据库值时可以从消息队列中重新读取这些值然后再次进行删除或者更新。
这种做法引入消息队列可能会增加更多的维护成本。如果重试超过的一定次数还是失败需要向业务层发送报错信息。 注意即使这两个操作执行时都没有失败但是当有大量并发请求时应用还是可能会读到不一致的数据。还是分以下两种情况讨论 先更新数据库再删除缓存
假设线程 A 删除了数据库中的值但还没来得及删除缓存线程 B 就开始读取数据了那么此时线程 B 查询缓存时就会直接从缓存中读取到旧值。不过这种情况下如果其他线程并发读缓存的请求不多那么就不会有很多请求读取到旧值。并且线程 A 一般也会很快删除缓存值这样其他线程再次读取时就会发生缓存缺失然后去数据库中获取最新的值因此这种情况对业务的影响较小。
先删除缓存再更新数据库延迟双删
我们先删除缓存然后更新数据库的值更新完数据库值以后我们可以让线程先 sleep 一小段时间再进行一次缓存删除操作。
这就是延迟双删伪代码如下
redis.delKey(K)
db.update(K)
Thread.sleep(T)
redis.delKey(K)有了sleep 的这段时间即使有其他缓存从数据库读取到旧的值并重新放到缓存中我们也能再次删除保证缓存中会是新的值。至于sleep的这个时间如何确定以实际业务执行时间为准。
总结
删除缓存或更新数据库失败导致的数据不一致我们可以使用重试机制确保操作成功。在删除缓存、更新数据库的这两步操作中有其他线程的并发读导致其他线程读取到旧值我们可以使用延迟双删方案解决。