MySQL与Redis的缓存同等性问题

打印 上一主题 下一主题

主题 970|帖子 970|积分 2910

MySQL与Redis的缓存同等性问题

前言

在学习中,为了提高数据的读取效率,我们每每会利用Redis来作为MySQL数据的缓存,那么,天然就产生了二者间数据的同等性问题。
想要对MySQL和Redis进行数据处置惩罚,天然会产生以下问题:


  • MySQL与Redis操作的时序问题

    • 更新与删除的选择实时序问题

下面我们来一一分析:
先操作MySQL

先删除MySQL中数据

这种情况下,当我们选择先将MySQL中的数据删除时,如果后续写入新数据失败,新数据就很有可能会丢失,我们就完全失去了这条数据,这是难以接受的。以是我们还是来看看先更新MySQL的情况吧:
先更新MySQL中数据

这种情况下,当客户端修改一个数据时,我们先将MySQL中数据更新为最新状态,然后再操作Redis(如果第一步更新MySQL数据失败,就不会继续操作Redis了,此时MySQL和Redis中的数据都还是老数据,也是处于同等状态,可以接受):
再更新Redis中数据

试想如许一种情况:
线程A和线程B按以下次序实行:

  • 线程A缓存未命中,然后从MySQL中读到数据c=1
  • 线程B想将数据c=1修改为c=2
  • 线程B先更新MySQL成功,再更新Redis数据c=2(岂论更新Redis成功与否)
  • 线程A写回Redis数据c=1
可以看到,此时MySQL中是新数据c=2,Redis中却是老数据c=1,处于不同等状态。在Redis中该数据自动过期,大概再次更新该数据之前,客户端都会读到Redis中的老数据(脏数据)。
不过读操作,每每比写操作更快速,也就是说大多数情况下,线程A等线程B操作完了再写回Redis的情况不会出现。
但是,对于并发更新的情况,可能会出现多个线程并发更新Redis数据,导致老数据覆盖新数据的情况,也会造成不同等状态。
再删除Redis中数据

与上面“再更新Redis中数据”的情况类似,可能会出现线程B删除完Redis数据后,线程A又写回老数据的情况。
但是,对于并发更新的情况,就算多个线程并发删除Redis数据,也能够包管删除老数据,不会造成不同等状态。
当然,如果删除Redis失败了,Redis中还是会留下老数据,造成不同等状态。
先操作Redis

先删除Redis中数据

再更新MySQL中数据

试想如许一种情况:
线程A和线程B按以下次序实行:

  • 线程B想将数据c=1修改为c=2
  • 线程B先删除Redis中数据成功
  • 线程A缓存未命中,然后从MySQL中读到数据c=1
  • 线程B更新MySQL中数据c=2
  • 线程A写回Redis数据c=1
可以看到,此时MySQL中是新数据c=2,Redis中却是老数据c=1,处于不同等状态。在Redis中该数据自动过期,大概再次更新该数据之前,客户端都会读到Redis中的老数据(脏数据)。
别的,对于并发更新的情况,可能会出现多个线程并发更新MySQL数据,导致老数据覆盖新数据的情况,也会造成不同等状态。
再删除MySQL中数据

这种情况下,当我们选择将MySQL中的数据删除时,如果后续Redis中的新数据丢失(磁盘存储相对内存存储的可靠性更高),我们就完全失去了这条数据,这是难以接受的。
总结

Cache-Aside (旁路缓存)

综上所述,我们每每会选择 先更新MySQL中数据-再删除Redis中数据 的方案。
以上所述所有的方案,有一个统称:Cache-Aside (旁路缓存)
直读 与 同步/异步直写

别的,如果我们将缓存的业务直接从其它业务代码中抽取出来,给其它业务提供一个缓存抽象层,将缓存的操作全部放在这个缓存抽象层中独立存在,也就是缓存的解耦。
如许,主体业务就只必要与抽出来的缓存层进行交互,无需再关心数据的同等性,直接读/写缓存层,也就是直读直写
直读(Write-Through)

客户端(也可以是其他业务层)直接读取Redis缓存,如果缓存未命中,从MySQL中读取数据后,再写回Redis,然后再返回给客户端。
直写(Write-Through)

客户端(也可以是其他业务层)直接先更新Redis缓存,然后再更新MySQL,然后再返回数据给客户端。
上面的是同步直写,如果在更新MySQL的同时,异步将数据返回给客户端,那么就叫异步直写(Write-Behind)
canal

别的,为了提高体系的可用性,我们可以共同一些成熟的中间件,例如:
利用Canal监控MySQL的binlog日记,自动通知缓存业务MySQL中的数据进行了什么修改,可以让我们的体系迅速知道MySQL的数据改动,耽误极低。
在缓存业务中,我们每每还可以引入消息队列,提高数据传输的可靠性,例如:
当Canal监控到MysQL数据改动后,将监控数据发送到RabbitMQ,由订阅了相干Topic的缓存业务消费监控数据并进行处置惩罚,可以有效避免数据传输中失败、丢失等问题。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

玛卡巴卡的卡巴卡玛

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表