青州网站设计,店名logo设计在线生成,广西壮族自治区成立于哪一年,延安有哪些做网站的公司实际项目中有可能会使用Redis缓存数据#xff0c;那么在更新数据的时候如何保证数据库中的数据和Redis缓存的数据一致#xff0c;缓存同步策略的选择是一个很重要的问题。网上有各种说法#xff0c;大概总结有以下几种#xff0c;看看每种方案是否可行以及存在的问题和适用…实际项目中有可能会使用Redis缓存数据那么在更新数据的时候如何保证数据库中的数据和Redis缓存的数据一致缓存同步策略的选择是一个很重要的问题。网上有各种说法大概总结有以下几种看看每种方案是否可行以及存在的问题和适用场景。
1、先更新Redis再更新数据库 (不可行 )
数据库是比较复杂的而且还会涉及事务因为超时等原因更新操作失败的可能性较大这种方案很可能因为数据库更新失败导致缓存和数据库的数据不一致。 如上图所示如果第2步更新数据库失败了那么缓存的数据被更新为20和数据库值10不一致了。 这种情况可能会想到补救措施数据库更新失败了再将Redis数据做逆向操作进行回退但是如果Redis数据回退操作也失败了呢甚至还要继续针对这种失败做重试显然事情越做越复杂了这种方式不可行。 2、先更新数据库再更新Redis (部分场景可用不推荐 )
上面的方案不可取这种先更新数据库的是否就可行呢假设有两个请求更新数据时序图如下 如果是并发量不高对一致性要求没有特别高时如上图更新完数据库再更新Redis没有问题。 如果是并发量较高如图所示这种场景下虽然请求1和请求2先后完成数据库更新但更新缓存时却是请求2和请求1的顺序那就很可能会把旧数据更新到缓存中导致数据不一致。 3、先删除Redis再更新数据库访问的时候再加载数据到缓存 (不可行 )
这里同样以两个请求的场景为例时序图如下 从图上可以看到当并发场景下如果请求1更新耗时较长还未来得及更新数据库中的值请求2已经先读取了旧值并加载到缓存中了。这种也会导致两边数据不一致而且并发量很高的时候这种概率也会更大。 针对这个方案存在的问题可以在请求1更新完数据库后再对Redis做一次删除操作。也就是缓存双删 4、先删除Redis再更新数据库再删除Redis访问的时候再加载数据到缓存缓存双删 这种方案一定程度上解决了方案4数据不一致的问题但是也有一个关键点如上图所示必须保证第6步删除缓存操作在第5步回写入缓存操作之后执行否则还是会有问题。那么这又引出了另外两个问题
问题一如何保证第二次删除缓存一定在回写后面执行呢 关于双删的这个问题网上有方案是让请求1删除缓存时等待xxx毫秒这个方案似乎可行但是这个时间不好控制还是会存在一定风险。 另外也有博主给出的建议方案是将删除请求加入消息队列异步串行化处理删除 问题二如果双删失败了怎么办 同样的网上也有方案给redis加一个缓存过期时间、删除加入消息队列利用消息队列的重试机制、自己记录删除失败进行重试等 5、先更新数据库再删除Redis访问的时候再加载数据到缓存 这种方案除了请求2第一次查询这一次不一致还有另一个极端场景会存在数据不一致。请求1更新数据节点缓存刚好失效了另一个请求2刚好这时读取缓存没有进而读了数据库旧值如下图所示 这个极端场景需要满足缓存更好失效而且请求2读取数据库及回写缓存耗时较请求1更新数据库更长发生的概率非常小可以忽略所以相比较而言方案5是最推荐的处理策略。
通过以上几种处理方案的分析可以看到不管哪种方案都存在一定的问题在满足实时性的条件下尽量保证不一致出现的概率更低或者不一致持续的时间非常短暂避免长期不一致。非要满足强一致性可能就需要考虑使用锁的方案了。
总的来说针对缓存同步更推荐的方式是缓存中的数据不由数据更新操作主动触发统一在需要使用的时候按需加载数据更新后及时删除缓存中的数据。