Redis缓存和数据库的一致性(六)

一:读缓存

缓存+数据库读写的模式,就是  -——读的时候,先读缓存,缓存没有的话,就读数据库,然后取出数据后放入缓存,同时返回响应。

原因有二:

(1)如果是一个数据库写多读少的业务场景求,采用这种方案就会导致,数据压根还没读到,缓存就被频繁的更新,浪费性能。

(2)如果你写入数据库的值,并不是直接写入缓存的,而是要经过一系列复杂的计算再写入缓存。那么,每次写入数据库后,都再次计算写入缓存的值,无疑是浪费性能的。显然,删除缓存更为适合。

所以采用lazy思想,用到的时候再去查。

 

出现分歧的点主要在于——更新的时候,是先删除缓存,再更新数据库。还是先更新数据库,再更新缓存?

二、先删缓存,再更新数据库:

存在的问题:①并发请求的问题,会使缓存数据和数据库数据出现不一致。

                      ②删除缓存失败问题

针对并发问题导致的数据不一致,解决方案:①采用双删策略

更新数据时先删除缓存数据,然后将数据写入数据库,写入完成后再次删除缓存,再写入缓存并设置缓存过期时间

这种方式虽然一定程度上保证了数据的一致性,但是面对上述问题,同样会存在极短时间内数据不一致,也就是写入数据库,到再次删除缓存这段时间。

 

②加分布式锁

如果要求数据的强一致性,那么我们就需要牺牲一点性能了,采用加分布式锁的方式了:

写: - 先清除缓存 - 对key加分布式锁 - 更新数据库 - 更新缓存,释放锁

读:

  • 查询缓存,查询到结果则直接返回
  • 没有查询到结果则加分布式锁,读取数据库,再写入缓存释放锁
  • 如果没有获取到锁,则等一点时间重试,获取到锁后,先去缓存查询,如果查询到直接返回,没查询到则读取数据库,写入缓存,释放锁。

这种解决方式,因为引入了分布式锁解决了并发的问题,也解决了因为删除缓存可能导致的缓存穿透等问题,当然这种方式也牺牲了一部分性能。

当然,我们也可以给key设置一个有效期,来保证最终一致性。

 

 

三、先更新数据库,再删缓存:facebook也是使用的这种删除方法

存在的问题:①并发请求的问题,会使缓存数据和数据库数据出现不一致。但是这种情况出现的概率非常非常低,可认为不会发生。

假设这会有两个请求,一个请求A做查询操作,一个请求B做更新操作,那么会有如下情形产生:

(1)缓存刚好失效
(2)请求A查询数据库,得一个旧值
(3)请求B将新值写入数据库
(4)请求B删除缓存
(5)请求A将查到的旧值写入缓存

如果发生上述情况,确实是会发生脏数据。然而,发生这种情况的概率又有多少呢?发生上述情况有一个先天性条件,就是步骤(3)的写数据库操作比步骤(2)的读数据库操作耗时更短,才有可能使得步骤(4)先于步骤(5)。但是数据库的读操作的速度一般是远快于写操作的,因此步骤(3)耗时比步骤(2)更短,这一情形很难出现。

                      ②删除缓存失败问题

解决并发请求产生的问题(虽然概率极低)方法:

①:给key设置一个有效期

②:异步延时双删:更新数据库,删除缓存,再删除一次缓存(起一个异步线程,例如1s后删除)

 

所以这种情况最主要的问题是解决删除缓存失效的问题,解决方法主要围绕删除缓存失败了如何进行重试上。

方案①:

   1)更新数据库数据;
(2)缓存因为种种问题删除失败
(3)将需要删除的key发送至消息队列
(4)自己消费消息,获得需要删除的key
(5)继续重试删除操作,直到成功

然而,该方案有一个缺点,对业务线代码造成大量的侵入。于是有了方案②,在方案中,启动一个订阅程序去订阅数据库的binlog,获得需要操作的数据。在应用程序中,另起一段程序,获得这个订阅程序传来的信息,进行删除缓存操作。

方案②:

 

(1)更新数据库数据
(2)数据库会将操作信息写入binlog日志当中
(3)订阅程序提取出所需要的数据以及key
(4)另起一段非业务代码,获得该信息
(5)尝试删除缓存操作,发现删除失败
(6)将这些信息发送至消息队列
(7)重新从消息队列中获得该数据,重试操作。

备注说明:上述的订阅binlog程序在mysql中有现成的中间件叫canal,可以完成订阅binlog日志的功能。另外,重试机制,采用的是消息队列的方式。如果对一致性要求不是很高,直接在程序中另起一个线程,每隔一段时间去重试即可。

 

总结:最经典的缓存+数据库读写的模式,就是 Cache Aside Pattern。 - 读的时候,先读缓存,缓存没有的话,就读数据库,然后取出数据后放入缓存,同时返回响应。 - 更新的时候,先更新数据库,然后再删除缓存。

          根据具体业务来选择具体的处理方式,如果要保证数据的强一致性的话就需要加锁,这时候就会使系统的吞吐量下降。

 

https://blog.csdn.net/a745233700/article/details/88081219

https://zhuanlan.zhihu.com/p/142502900

 

 

 

Guess you like

Origin blog.csdn.net/weixin_46217160/article/details/115796383