Redis和MySQL的双写一致性系列问题

1.什么是一致性

顾名思义,就是数据的一致性,如果是在分布式系统中,那就是各节点中的数据保持一致。
一致性分为

  1. 强一致性
  2. 弱一致性
  3. 最终一致性

强一致性:这种是符合用户直观感觉的,就是系统写入什么,读出来的就是什么。读写是实时的,用户体验行好,但是对系统的性能影响非常大。
弱一致性:这种级别约束了系统再写入成功后,不承诺立即可以读到写入的值,也不承诺多久之后数据可以达到一致,但会尽可能的保证在某个时间级别后达到一致状态。
最终一致性:这种级别约束了系统在一定时间内,数据可以达到一致性。是业界的大型分布式系统比较推崇的模型。

2.三种缓存模式

缓存可以提升性能,缓解数据库压力,但是使用缓存可能会导致数据不一致性的问题。有三种缓存模式比较常用。

  1. Cache-Aside Pattern
  2. Reah/Write-Through Pattern
  3. Write behind Pattern

Cache-Aside Pattern:旁路缓存模式
读的过程:
1.读数据时,先读缓存,缓存如果命中直接返回数据;
2.缓存如果不命中,就去读数据库,从数据库中取出数据,然后放入缓存,返回数据。
写的过程:先更新数据库,再删除缓存。
Reah/Write-Through Pattern:读写穿透

这个模式和第一种很像,但是把缓存和数据库认为是一体的,应用的读写都针对于缓存,缓存来维护更新数据库。这样可以让程序代码变得更加简洁。

Write behind Pattern:异步缓存写入模式
和第二种类似,但是第二种缓存和数据库的更新是事务性的,保证了强一致性;而第三种是异步的,先更新缓存,通过异步的方式来更新数据库,缓存和数据库的一致性不强。

3.操作缓存的时候,删除还是更新

在第一种模式中,采用了删除缓存,为什么不是更新缓存呢?
如下例子,有两个线程A和B同时发出一个写操作,

  1. 线程A先写,更新数据库
  2. 线程B后写,更新数据库
  3. 由于网络等原因,线程B先更新了缓存
  4. 线程A后更新了缓存

结果,数据库里为B的值,缓存里为A的值,就成了脏数据,如果后续不再执行写操作,则读出去的数据都是脏数据。

如果是删除缓存则

  1. 线程A先写,更新数据库
  2. 线程B后写,更新数据库
  3. 由于网络等原因,线程B先删除了缓存
  4. 线程A后删除缓存

结果,数据库里为B的值,缓存中没有值,一旦有读操作进来,cache miss,然后去数据库中读,读到的是B的值。
因此,更新的副作用是数据不一致性,删除的副作用仅仅是多一次cache miss。
另外,更新缓存相对于删除缓存还有两点劣势:

  1. 如果写入的缓存值,是经过复杂计算才得到的,更新缓存频率高的话就浪费了大量的性能
  2. 在写场景多,读场景少的情况下,数据不需要读的时候,可能发生了很多次写,太浪费性能。

4.双写情况下,先操作数据库还是缓存

如果是先操作缓存,则出现如下情况
线程A做写操作,线程B做读操作。

  1. 线程A发起写操作,删除缓存
  2. 线程B发起读操作,cache miss
  3. 线程B去读数据库,写入缓存并返回
  4. 线程A更新数据库

结果,数据库和缓存出现数据不一致性。

如果是先操作数据库,则出现如下情况:

  1. 线程A发起写操作,更新数据库
  2. 线程B发起读操作,返回
  3. 线程A删除缓存

结果,线程B读的是过期数据,但是接下来的读操作则会MISS,然后去数据库读取正确数据并放入缓存中。

先删缓存的解决方法

缓存延时双删

  1. 先删除缓存
  2. 更新数据库
  3. 休眠一会(读业务耗时+几百毫秒,保证读请求结束),再删除缓存

但是,无论是先更新数据库在删除缓存,还是延时双删,如果最后一步的删除缓存操作失败,就会导致脏数据。
因此,可以引入删除缓存重试机制:

  1. 写请求更新数据库
  2. 缓存因为某些原因,删除失败
  3. 把删除失败的key放入消息队列
  4. 消费消费队列的信息,获得删除失败的key
  5. 重试删除缓存操作
    既可以保证所有缓存删除成功。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LSY_HELLOWORLD

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值