如何保证缓存和数据库的数据一致

本篇文章主要讨论常见的集中缓存的使用方案,以及如何解决数据和缓存的一致性

常见的缓存模式

Cache-Aside Pattern

我们常见的缓存方案,可以说我们大部分都采用这种方案,见下面:

avator

Read-Through/Write through(读写穿透)

本质上和Cache-Aside Pattern类似,只是在程序和缓存中增加了一层Cache Provider,读写如果未命中由Cache Proxy来负责和缓存交互。减少程序开发的复杂性,需要中间件支持

Read-Through

avator

Write through

avator

Write behind

和Read-Through/Write through类似,区别是Write behind模式下,数据都是写到Cache Provider,由Cache Provider异步的刷到数据库中,听着是不是很熟悉,对Mysql的WAL异步刷盘就是这种模式

avator

如何保证缓存和数据库的数据一致

这里是以常见的Cache-Aside Pattern来讨论,正确操作缓存的姿势是

avator

这里要注意俩点

不是更新缓存而是要删除缓存

如果更新缓存不是删除缓存在并发场景下会出现脏数据里有如下:

avator

  1. 线程A先发起一个写操作,第一步先更新数据库
  2. 线程B再发起一个写操作,第二步更新了数据库
  3. 由于网络等原因,线程B先更新了缓存
  4. 线程A更新缓存。

这时DB是B操作后的数据,缓存是A操作的数据

要先操作数据库而不是先操作缓存

如果先操作缓存不是先操作数据库会在并发场景下会出现脏数据里有如下:

avator

  1. 线程A发起一个写操作,第一步del cache
  2. 此时线程B发起一个读操作,cache miss
  3. 线程B继续读DB,读出来一个老数据
  4. 然后线程B把老数据设置入cache
  5. 线程A写入DB最新的数据

这时DB是A操作后的数据,缓存是B操作后的数据。