Skip to main content

8、缓存双写一致性

Y-aong...About 5 minredis缓存双写一致性

8、缓存双写一致性

一、基本思路

redis中有数据需要和数据库中的数据一致

redis中没有数据,数据库中的值要是最终值

二、canal简介

1、定义

canal是基于msyql binlog日志的增量订阅和消费的组件

2、作用

  • 数据库镜像
  • 数据库实时备份
  • 带有业务逻辑的增量数据处理

3、工作原理

canal 工作原理
canal 模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,向 MySQL master 发送dump 协议
MySQL master 收到 dump 请求,开始推送 binary log 给 slave (即 canal )
canal 解析 binary log 对象(原始为 byte 流)

4、基本操作

  • 开启mysql的binlog写入功能
  • 授权cannal连接msyql
  • 重启mysql

二,缓存数据的双写一致性探讨

1、目的

要达到缓存数据和mysql数据最终一致

2、方案一 、先更新数据库,再更新缓存

问题有可能更新缓存失败,造成缓存数据为旧数据,缓存数据和mysql数据不一致

3、方案二、先删除缓存,再更新数据库

问题一、缓冲数据和mysql数据不一致

A线程先删除缓存数据,再去更新mysql,此时来了一个请求B线程,B线程查询缓存没有查到,然后从数据库查询,查询结束将查到的数据写到缓存中,后面再来请求,发生缓存数据和mysql数据不一致,有可能一直脏下去

总结流程:
(1)请求A进行写操作,删除缓存后,工作正在进行中......A还么有彻底更新完
(2)请求B开工,查询redis发现缓存不存在
(3)请求B继续,去数据库查询得到了myslq中的旧值
(4)请求B将旧值写入redis缓存
(5)请求A将新值写入mysql数据库
上述情况就会导致不一致的情形出现。

时间线程A线程B出现的问题
t1请求A进行写操作,删除缓存后,工作正在进行中......
t21 缓存中读取不到,立刻读mysql,由于A还没有对mysql更新完,读到的是旧值。
2 还把从mysql读取的旧值,写回了redis
1 A还更新完mysql,导致B读到了旧值
2 线程B遵守回写机制,把旧值写回redis,导致其它请求读取的还是旧值,A白干了。
t3更新mysql数据库的值,overredis是被B写回的旧值,mysql是被A更新的新值。
出现了,数据不一致问题。

4、方案三、 先更新mysql数据,最后删除缓存

假如缓存失败,或者是删除未完成,导致请求再次访问,redis命中缓存,读取的还是旧值

5、解决方案

image-20230422140030329
image-20230422140030329

总结来说

第一步、更新完成数据库的时候,删除缓存数据

第二步、此时如果来了一个请求查询,此时缓存无数据,查询数据库,但是查询数据库的时候加个锁(for update)并且休眠一段时间(这个时间为缓存数据插入到数据库的两倍)

第三步、将缓存数据保存的任务放到消息队列中(celery),设置异常重试策略,如果多次插入失败,通知运维人员

6、问题

为什么要加休眠时间

这个休眠时间为了保证将数据写入到缓存中

为什么要加锁

加锁的原因是为了在此期间数据再次发生变化

三、总结

在大多数业务场景下,我们会把Redis作为只读缓存使用。假如定位是只读缓存来说,
理论上我们既可以先删除缓存值再更新数据库,也可以先更新数据库再删除缓存,但是没有完美方案,两害相衡趋其轻的原则

个人建议是,优先使用先更新数据库,再删除缓存的方案。理由如下:

1 先删除缓存值再更新数据库,有可能导致请求因缓存缺失而访问数据库,给数据库带来压力,严重导致打满mysql。

2 如果业务应用中读取数据库和写缓存的时间不好估算,那么,延迟双删中的等待时间就不好设置。

四、延迟双删策略

线程A更新数据库,然后删除缓存休眠一段时间,再删除缓存

线程B查询,缓存中没有数据,然后写缓存,

这个时候数据不一致的窗口期为两次删除缓存之间的时间间隔

五、两种方式的对比

方式一,更新数据库删除缓存,查询数据库的时候进行加锁,防止写入缓存的时候会降低并发性,延误并发时间为插入数据库的时间,没有缓存数据和mysql数据不一致的时候

方式二,更新数据库删除缓存,休眠后再次删除缓存,这种的话会出现不一致的时间窗口,但是时间间隔为两次删除之间的时间间隔。保证的高并发的要求

Comments
  • Latest
  • Oldest
  • Hottest
Powered by Waline v2.15.8