为什么会发生数据库和缓存数据的不一致问题。

一致性是什么,一致性包含了以下两种:

  1. 缓存中有数据,那么数据库的数据必须要和缓存的数据要一致。
  2. 缓存中没有数据,在数据库值必须要是最新的数据。

不符合以上两种情况的数据就是发生了数据不一致问题,对于读写缓存来说,就会发生这样的问题,此时我们要需要相应的策略去做做同步还是异步:

  1. 同步写回策略:就是写入缓存时,必须要写入数据库,保证数据一致性。
  2. 异步写回策略:想写入缓存,等到缓存失效或者淘汰的时候,再写入数据库,此时如果还没有写入数据库,缓存就挂了,这样数据就会丢失,数据库就没有最新的值了。

对于读写缓存来说,要想数据一致性就要采用同步写回策略,如果数据不是必要的数据,可以采用数据的异步写回策略,比如电商商品的非重要参数。
如果我们采用同步写回策略,就要保证写入缓存和数据的数据能到保证原子性,也就是说,缓存和数据的数据要同时增删改,一起更新或者都不更新。

删除数据怎么保Redis和数据库的一致性问题

数据删除时,先选择删除数据库还是先选择缓存。 一,选择先删除数据库。

  1. 当我们删除数据的时候,先选择删除数据库,后选择删除缓存时,会在一定事件内发生数据不一致问题,比如线程A和B还有其他,A在删除数据数据的时候,B和其他线程来读取数据,这个时候,B和其他线程会读取到旧值,当A线程删除完成删除缓存后就可以消除读取旧值问题。这个会造成一小段时间内会读取到旧值。
  2. 当我们删除数据的时候,先选择删除数据库,在删除缓存时,删除缓存失败了,会造成旧数据一直会读取。比如线程A和B还有其他,A在删除数据库成功了,A和其他线程删除缓存失败。就会造成B和其他线程一直在读取旧值。解决方法选择删除数据库的时候,通过消息中间件MQ或者Kafka发送一条删除指令,在数据库删除完成之后启动一个线程去删除缓存,如果删除失败一直做删除操作,一直到删除成功。

二,选择先删除缓存。

  1. 1.当我们删除数据的时候,先选择删除缓存,后选择删除数据库,会导致缓存出问题,比如线程A和B还有其他线程,A线程删除了缓存,还没有来及删除数据库(比如网络延迟),此时B和其他线程来读取消息,会发生缓存中没有数据,就会去数据库查询数据,数据库中的值还是以前的值,这样会造成缓存被重新更新为旧值,解决方法:可以使用缓存双删,可以把线程A休眠一段时间,这个时间是B线程读取数据被把数据写到缓存中的时间,这个时间还需要开发者在测试中找到比较准确的时间,来设置这个A线程的休眠时间。
  2. 当我们删除数据的时候,先选择删除缓存,后选择删除数据库时删除失败了,这样会造成缓存数据一直在数据库没有被删除,导致一直读取的时旧值,这样可以通过消息中间件去操作,直到数据库更新成功,在去删除缓存,这样的实现用到了缓存双删和消息中间件。

三,自我认为还是选择先删除数据库在去删缓存。

  1. 1.首先如果删除缓存,缓存缺失,会给数据库带来一定的压力。
  2. 2.如果业务中读数据和写缓存的时间控制的不好设置,那么双删的等待时间就不好设置。

四,如果业务中必须要准确的数据,保证数据一致性。

  1. 当删除数据库的值时,其他客户端短暂把并发请求暂存,等数据库删除和缓存更新之后再去发起请求,从而保证数据的一致性。这样下来并发就减小了。

添加数据怎么保Redis和数据库的一致性问题

一,选择先添加数据库。

  1. 当把数据先添加数据库时,添加缓存的操作出了问题,下一次查询数据导致缓存中没有数据,对数据库的压力较大。

二,选择先添加缓存。

  1. 当把数据先添加缓存时,添加数据库的操作出了问题,我们可以采用Mq或Kafka消息中间件发送添加指令,知道数据添加到数据库,则结束操作。

修改数据怎么保Redis和数据库的一致性问题
一.选择先更新数据库,对于读写缓存的读写并发操作

  1. 当先更新数据到新数据库时,数据库更新完毕后,在更新缓存,当缓存更新失败,会导致访问命中的缓存一直都是旧值,直到这个缓存失效或者淘汰,才能得到新的数据。
  2. 比如A和B其他线程,A线程更新数据库,数据库更新数据完毕后,更新缓存,当缓存更新失败,B和其他线程就会一直读取旧值,直到此数据失效或者淘汰之后,才能读取到新的值。

二.选择先更新缓存,对于读写缓存的读写并发操作

  1. 当先更新数据到缓存,数据更新完毕之后,在更新数据库,此时数据库跟新失败,会导致访问命中的缓存是最新值,当数据失效或者淘汰之后再去读取数据,还是读取的数据库的旧值,这样数据就会不一致。比如A和B其他线程,A线程先去更新缓存的值时,更新数据库的值失败之后,B和其他线程读取的时最新的数据,等到数据失效,B和其他线程读取的值就是旧值。

解决以上者两种修改操作,我们可以利用消息中间件可以做到,当失败了一直等到数据一致,保证数据库能更新,和缓存数据能够写进去,和删除的效果是一致的。

三.选择先更新数据库,对于读写缓存的写写并发操作

  1. 当先更新数据到数据库时,有两个线程A和B线程时,当A线程去修改数据库,B线程也去修改数据库,B线程去修改缓存,A线程在去修改缓存,会造成数据不一致问题。

四.选择先更新缓存,对于读写缓存的写写并发操作

  1. 当先更新数据到缓存时,有两个线程A和B线程时,当A线程去修改缓存,B线程也去修改缓存,B线程去修改数据库,A线程在去修改数据库,会造成数据不一致问题。

解决以上两种方案是,对于写请求,需要配合分布式锁使用。写请求进来时,针对同一个资源的修改操作,先加分布式锁,这样同一时间只允许一个线程去更新数据库和缓存,没有拿到锁的线程把操作放入到队列中,延时处理。用这种方式保证多个线程操作同一资源的顺序性,以此保证一致性。

综上使用读写缓存读写并发的时候,可以使用消息中间件来维护数据不一致问题,在读写模式下对业务造成的影响不是很大。当使用读写缓存写写并发的时候,可以使用加分布式锁来维护数据不一致问题。

另外,读写缓存模式由于会同时更新数据库和缓存,优点是,缓存中一直会有数据,如果更新操作后会立即再次访问,可以直接命中缓存,能够降低读请求对于数据库的压力(没有了只读缓存的删除缓存导致缓存缺失和再加载的过程)。缺点是,如果更新后的数据,之后很少再被访问到,会导致缓存中保留的不是最热的数据,缓存利用率不高(只读缓存中保留的都是热数据),所以读写缓存比较适合用于读写相当的业务场景。