如何保证Redis与数据库的一致性

目录

先上一个错误操作示范

正确姿势

一、缓存失效(Cache Aside Pattern)

策略(Facebook论文范例):

问题:

二、读/写透明(Read/Write Through Pattern)

策略:

三、写回调( Write Back)

策略:


 

先上一个错误操作示范

操作方法:先删除缓存,然后再更新数据库,而后续的操作会把数据再写入到的缓存中。

存在的问题:查询请求没hit到缓存会把旧数据更新到缓存中。

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

 

正确姿势

一、缓存失效(Cache Aside Pattern)

策略(Facebook论文范例)

  • 失效:应用程序先从cache取数据,没有得到,则从数据库中取数据,成功后,放到缓存中。
  • 命中:应用程序从cache中取数据,取到后返回。
  • 更新:先把数据存到数据库中,成功后,再让缓存失效。

问题:

1、为什么不写完数据库后再更新缓存

并发两个写操作可能会导致脏数据。

2、该策略存在什么问题?

问题1 脏读:一个查询缓存请求,一个更新缓存请求。查询缓存没有hit,从数据库查出了旧数据,此时有个更新请求过来,更新数据库后把缓存设为了失效。刚才查询请求此时把旧数据更新到缓存中,于是缓存中的数据会一直是脏数据。

问题2 更新缓存失效失败:概览太低不考虑

解释:实际发生的概览非常低,需满足两个条件:1、读缓存时缓存失效,而且并发着有一个写操作 2、读操作必需在写操作前进入数据库操作,而又要晚于写操作更新缓存。由于一般写操作时间远大于读操作时间,所以发生概率很低。要么通过2PC(太慢)或是Paxos(太复杂)协议保证一致性,要么就是拼命的降低并发时脏数据的概率。

 

二、读/写透明(Read/Write Through Pattern

策略:

Read Through

Read Through 套路就是在查询操作中更新缓存,也就是说,当缓存失效的时候(过期或LRU换出),Cache Aside是由调用方负责把数据加载入缓存,而Read Through则用缓存服务自己来加载,从而对应用方是透明的。

Write Through

Write Through 套路和Read Through相仿,不过是在更新数据时发生。当有数据更新的时候,如果没有命中缓存,直接更新数据库,然后返回。如果命中了缓存,则更新缓存,然后再由Cache自己更新数据库(这是一个同步操作)

 

三、写回调( Write Back)

策略:

在更新数据的时候,只更新缓存,不更新数据库,而我们的缓存会异步地批量更新数据库。

优点:让数据的I/O操作飞快无比。

缺点:数据不是强一致性的,而且可能会丢失。

 

 

参考

1、缓存更新的套路:

https://coolshell.cn/articles/17416.html#Write_Behind_Caching_Pattern

 

你可能感兴趣的:(redis)