Redis和MYSQL双写一致性分析

缓存的问题

  • 缓存雪崩(大量数据集中过期);

  • 缓存击穿(热点数据过期);

  • 缓存穿透(缓存和数据中都不存在该数据)

缓存淘汰

volatile-random,volatile-ttl,volatile-lru,volatile-lfu

allkeys-random,allkeys-lru,allkeys-lfu

读写缓存

  • 同步直写: 写redis,同时也写数据库;

  • 异步写回:先写redis,然后等redis淘汰数据时,同步写回数据到数据库中。

三个经典的缓存模式

  • Cache-Aside Pattern: 旁路缓存模式

  • Read-Through/Write-through

  • Write-behind

1. Cache-Aside Pattern

Cache-Aside读流程

读请求

命中缓存 - 返回

没命中 - 读数据 - 更新缓存 - 返回

Cache-Aside 写流程

写请求

更新数据库 - 删除旧缓存

2. Read-Through/Write-Through(读写穿透)

Read-Through: 通过缓存抽象层Cache-Provider来操作读

读请求

命中缓存 - 返回

没命中 - 读数据 - 更新缓存 - 返回

Write-Through: 通过缓存抽象层Cache-Provider来操作写

写请求

更新数据库, 同时设置更新缓存

3. Write-behind (异步缓存写入)

跟Read-Through/Write-Through有相似的地方,都是由Cache Provider来负责缓存和数据库的读写。

它们又有个很大的不同:

Read/Write-Through是同步更新缓存和数据的,

Write-Behind则是只更新缓存,不直接更新数据库,通过批量异步的方式来更新数据库。

缓存和数据库的一致性不强,对一致性要求高的系统要谨慎使用。但是它适合频繁写的场景,MySQL的InnoDB Buffer Pool机制就使用到这种模式。

疑问解答:

1. 操作缓存的时候,到底是删除缓存呢,还是更新缓存? 答案是: 删除缓存。  更新缓存,容易造成缓存和数据库的数据不一致

2. 双写的情况下,先操作数据库还是先操作缓存? 答案是:先操作数据库。  先操作缓存,也容易造成缓存和数据库的数据不一致

4. 有3种方案保证数据库与缓存的保证弱一致性,最终一致性

个人觉得,在追求绝对一致性的业务场景,不适合引入缓存机制

前提: 存在删除缓存失败的情况,那么如何保证一致性?

1.  缓存延时双删: 延迟时间不好控制,第二次删除还是可能失败

2. 删除缓存重试机制(消息队列): 业务代码入侵

3. 读取binlog异步删除缓存

重试删除缓存机制还算可以,就是会造成好多业务代码入侵。其实,还可以这样优化:通过数据库的binlog来异步淘汰key

以mysql为例:

  • 可以使用阿里的canal将binlog日志采集发送到MQ队列里面

  • 然后通过ACK机制确认处理这条更新消息,删除缓存,保证数据缓存一致性

你可能感兴趣的:(redis,mysql,redis,mysql,缓存)