0%

Redis-缓存一致性

Redis缓存更新方案:

先更新数据库,再更新缓存

策略:

并发请求A、B。

A请求先更新数据库的值为1,然后在更新缓存前,请求B将数据库的值更新为2,紧接着也把缓存更新为2,然后A请求更新缓存为1。于是出现数据库缓存不一致,数据库为2,缓存为1

问题:存在并发更新同一条数据时,可能会出现数据库缓存不一致现象

先更新缓存,再更新数据库

策略:

并发请求A、B。

A请求先将缓存数据更新为1,然后在更新数据库前,B请求将数据库的值更新为2,紧接着将数据库更新为2,此时A请求将数据库的数据更新为1。于是出现了数据库缓存数据不一致

问题:存在并发更新同一条数据时,可能会出现数据库缓存不一致现象

先删除缓存,再删除数据库(Cache Aside 旁路更新策略①)

策略:

并发请求A、B。

请求A要将数据库值更新为21,所以请求A会删除缓存,此时请求B要读取该值,它查询缓存后没有命中,会从数据库中读取原值20,并写入到缓存中,然后请求A继续更改数据值为21。此时依然会出现数据库缓存不一致的现象

问题:

不更新缓存,而是删除缓存,然后后读取数据时,发现缓存中没有数据,在从数据库中读取数据更新到缓存中。分为【读策略】和【写策略】
写策略步骤:更新数据库数据,删除缓存中的数据
读策略步骤:如果读取的数据命中缓存,则直接返回数据;如果没有命中则从数据库中读取数据,然后更新缓存并返回

先更新数据库,再删除缓存(Cache Aside 旁路更新策略①)

策略:

并发请求A、B。

请求A查询某个值(假设缓存中不存在),此时请求A从数据中查询到值为20,在未写入缓存时请求B更新该值,先将数据库更新为21,并删除缓存。这是请求A把从数据库中读取到的数据20写入缓存。最终还是可能出现数据库缓存不一致的现象。

概率较低,缓存速度理论上不会出现该问题,但若删除缓存失败会导致缓存不一致。

问题:

不更新缓存,而是删除缓存,然后后读取数据时,发现缓存中没有数据,在从数据库中读取数据更新到缓存中。分为【读策略】和【写策略】
写策略步骤:更新数据库数据,删除缓存中的数据
读策略步骤:如果读取的数据命中缓存,则直接返回数据;如果没有命中则从数据库中读取数据,然后更新缓存并返回

问题解决方案:

原因:

两步操作,没有并发控制,因此遇到并发场景时,由于执行顺序不同导致数据不一致

方案:

  • 分布式锁

    同一时间同一数据只由一个请求操作更新缓存

  • 过期时间

    数据不一致 兜底方案

  • 保证数据库与缓存两个操作均成功

    • 重试(如@Retryable)
    • 订阅MySQL binlong,异步操作缓存(Canal,MQ)
注解:

①Cache Aside 旁路更新策略(不保证数据一致性)

释义:更新数据时,不更新缓存,而是删除缓存中的数据,在读取数据时,发现缓存中没有,再从数据库中读取数据,更新到缓存中。

来源:https://www.jianshu.com/p/1f7fa8f6cd59