老话新谈之缓存一致性

2023-06-09  本文已影响0人  cartoony

前言

缓存一致性常见的更新策略也比较多,如先更新数据库再更新缓存,先删缓存再更新数据库等等,我在理解的时候有些混乱,所以这个文章提供了一些理解上的技巧去理解缓存一致性。

为什么会有缓存一致性的问题

  1. 缓存与数据库是两套中间件,存在网络抖动之类的原因导致没有更新任一方的可能
  2. 数据库大多都是事务型的中间件,支持错误回滚,缓存大多是非事务型的中间件,这里缓存更新失败了没办法回滚

所以根因是缓存大部分不支持事务无法回滚。

怎么尽量解决缓存一致性的问题

操作二者必定有先后顺序,存在以下两个情况:

  1. 先操作缓存,再操作数据库。操作缓存成功,数据库更新失败,缓存无法回滚,数据不一致
  2. 先操作数据库,再操作缓存。操作数据库成功,缓存操作失败,可触发异常回滚数据库,数据一致

根据上述所列,只能先操作数据库,再操作缓存了。

操作缓存也分两种:

  1. 更新缓存数据,可能并发请求,后一请求更新缓存的数据被前一请求的更新覆盖了,导致数据不一致
  2. 删除缓存数据,并发请求,二者都使缓存失效,查询请求将数据库数据加载到缓存中,数据一致

根据上述所列,只能使缓存失效,查询请求加载数据到缓存中了。

所以,如果在不加任何重试措施的情况下,先操作数据库,再删除缓存是一个容错较好的方法。

缓存一致性的分类 & 存在的问题

Client 维护缓存 & 数据库的一致性

  1. 更新缓存 -> 更新数据库

    [图片上传失败...(image-446953-1686389497129)]

@startuml
Database Database   as DB
entity   Cache      as Cache

transaction1 -> Cache: update data
transaction1 <-- Cache: update result

transaction1 -> DB: update data
transaction1 <-- DB: update result

@enduml
  1. 更新数据库 -> 更新缓存

[图片上传失败...(image-e8b646-1686389497129)]

@startuml
Database Database   as DB
entity   Cache      as Cache

transaction1 -> DB: update data
transaction1 <-- DB: update result

transaction2 -> DB: update data
transaction2 <-- DB: update result


transaction2 -> Cache: update data
transaction2 <-- Cache: update result

transaction1 -> Cache: update data
transaction1 <-- Cache: update result

@enduml
  1. 删除缓存 -> 更新数据库

    [图片上传失败...(image-1038e9-1686389497129)]

@startuml
Database Database   as DB
entity   Cache      as Cache

transaction1 -> Cache: delete data

query1 -> DB: select data
query1 -> Cache: insert data

transaction1 -> DB: update result

@enduml
  1. 更新数据库 -> 删除缓存

[图片上传失败...(image-648517-1686389497129)]

@startuml
Database Database   as DB
entity   Cache      as Cache

query1 -> DB: select data
transaction1 -> DB: update result
transaction1 -> Cache: delete data
query1 -> Cache: insert data

@enduml

Server 维护缓存 & 数据库的一致性

  1. Read though/Write though

    • read though

    [图片上传失败...(image-f40f89-1686389497129)]

    @startuml
    Database Database   as DB
    entity   Cache      as Cache
    
    query -> repository: select data
    
    repository -> cache: get data
    repository -> DB: get data
    DB -> repository: return data
    repository -> cache: update data
    repository -> query: return data
    
    @enduml
    

[图片上传失败...(image-c23b3e-1686389497129)]

@startuml
Database Database   as DB
entity   Cache      as Cache

transcation -> repository: update data

repository -> cache: update data
repository -> DB: update data
DB -> repository: return result
repository -> transcation: return result

@enduml
  1. Write Behind

[图片上传失败...(image-b1768d-1686389497129)]

@startuml
Database Database   as DB
entity   Cache      as Cache

query -> repository: query data

repository -> cache: query data
repository -> DB: query data
DB -> repository: return data
repository -> cache: update data

repository -> query: return data

@enduml

[图片上传失败...(image-2eef9a-1686389497129)]

@startuml
Database Database   as DB
entity   Cache      as Cache

transcation -> repository: update data

repository -> cache: update data

repository -> DB: batch update data

@enduml

参考

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

本文首发于cartoon的博客

转载请注明出处:https://cartoonyu.github.io

上一篇下一篇

猜你喜欢

热点阅读