如何保证缓存与数据库数据一致性

redis系列之数据库与缓存数据一致性解决方案

重点文章:https://www.cnblogs.com/cxxjohnson/p/8519616.html

你只要用缓存,就可能会涉及到缓存与数据库双存储双写,你只要是双写,就一定会有数据一致性的问题,那么你如何解决一致性问题?

不是严格要求缓存+数据库必须一致性

一般来说,就是如果你的系统不是严格要求缓存+数据库必须一致性的话,缓存可以稍微的跟数据库偶尔有不一致的情况,最好不要做这个方案,读请求和写请求串行化,串到一个内存队列里去,这样就可以保证一定不会出现不一致的情况

串行化之后,就会导致系统的吞吐量会大幅度的降低,用比正常情况下多几倍的机器去支撑线上的一个请求。

严格要求缓存+数据库必须一致性

将不一致分为三种情况:

  1. 数据库有数据,缓存没有数据;

  2. 数据库有数据,缓存也有数据,数据不相等;

  3. 数据库没有数据,缓存有数据。

在讨论这三种情况之前,先说明一下使用缓存的策略,叫做 Cache Aside Pattern。简而言之就是

1. 首先尝试从缓存读取,读到数据则直接返回;如果读不到,就读数据库,并将数据会写到缓存,并返回。
2. 需要更新数据时,先更新数据库,然后把缓存里对应的数据失效掉(删掉)。

  1. 第一种数据库有数据,缓存没有数据:在读数据的时候,会自动把数据库的数据写到缓存,因此不一致自动消除.

  2. 第二种数据库有数据,缓存也有数据,数据不相等:数据最终变成了不相等,但他们之前在某一个时间点一定是相等的(不管你使用懒加载还是预加载的方式,在缓存加载的那一刻,它一定和数据库一致)。这种不一致,一定是由于你更新数据所引发的。前面我们讲了更新数据的策略,先更新数据库,然后删除缓存。因此,不一致的原因,一定是数据库更新了,但是删除缓存失败了。

  3. 第三种数据库没有数据,缓存有数据,情况和第二种类似,你把数据库的数据删了,但是删除缓存的时候失败了。

因此,最终的结论是,需要解决的不一致,产生的原因是更新数据库成功,但是删除缓存失败。

解决方案大概有以下几种:

  1. 对删除缓存进行重试,数据的一致性要求越高,我越是重试得快。

  2. 定期全量更新,简单地说,就是我定期把缓存全部清掉,然后再全量加载。

  3. 给所有的缓存一个失效期。

第三种方案可以说是一个大杀器,任何不一致,都可以靠失效期解决,失效期越短,数据一致性越高。但是失效期越短,查数据库就会越频繁。因此失效期应该根据业务来定。

并发不高的情况:

读: 读redis->没有,读mysql->把mysql数据写回redis,有的话直接从redis中取;

写: 写mysql->成功,再写redis;

并发高的情况:

读: 读redis->没有,读mysql->把mysql数据写回redis,有的话直接从redis中取;

写:异步话,先写入redis的缓存,就直接返回;定期或特定动作将数据保存到mysql,可以做到多次更新,一次保存;

你可能感兴趣的:(Redis)