更新数据时,是先删除缓存再更新DB,还是先更新DB再删除缓存?

当数据出现变化的时候,DB和redis的一致性就显得非常重要!

结论:并发的情况下,主要是看场景,和代价,进行选择。

目前有两种(基本思路)策略:

1.先删除缓存再更新DB

结论:产生脏数据的概率较大(若出现脏数据,则意味着再不更新的情况下,查询得到的数据均为旧的数据)

比如:两个并发操作,一个是更新操作,另一个是查询操作,更新操作删除缓存后,查询操作没有命中缓存,先把老数据读出来后放到缓存中,然后更新操作更新了数据库。于是,在缓存中的数据还是老的数据,导致缓存中的数据是脏的,而且还一直这样脏下去了。

2.先更新DB再删除缓存(使用场景多

结论:产生脏数据的概率较小,但是会出现一致性的问题;若更新操作的时候,同时进行查询操作,若hit,则查询得到的数据是旧的数据。但是不会影响后面的查询。(代价较小)

( 一个是查询操作,一个是更新操作的并发,首先,没有了删除cache数据的操作了,而是先更新了数据库中的数据,此时,缓存依然有效,所以,并发的查询操作拿的是没有更新的数据,但是,更新操作马上让缓存的失效了,后续的查询操作再把数据从数据库中拉出来。而不会像文章开头的那个逻辑产生的问题,后续的查询操作一直都在取老的数据。)

该设计模式产生脏数据的可能情况:

一个是读操作,但是没有命中缓存,然后就到数据库中取数据,此时来了一个写操作,写完数据库后,让缓存失效,然后,之前的那个读操作再把老的数据放进去,所以,会造成脏数据。

该情况出现的概率可能非常低,因为这个条件需要发生在读缓存时缓存失效,而且并发着有一个写操作。而实际上数据库的写操作会比读操作慢得多,而且还要锁表,而读操作必需在写操作前进入数据库操作,而又要晚于写操作更新缓存,所有的这些条件都具备的概率基本并不大。

强一致性 实现:通过2PC或是Paxos协议保证一致性;

生产过程中要么保持强一致性,要么拼命的降低并发时脏数据的概率,而Facebook使用了这个降低概率的玩法,因为2PC太慢,而Paxos太复杂。当然,最好还是为缓存设置上过期时间。

详细可参考:https://blog.csdn.net/zzh920625/article/details/78027534

拓展优化:

1.可以使用阿里的方法:CANAL,通过日志来保持一致性;

2.可以直接更新redis数据,先不入db,再某个时间段,再异步的方式通过redis更新DB;

猜你喜欢

转载自blog.csdn.net/qq_33999844/article/details/81531461