Redis缓存措施
Redis缓存一致性
措施:
- 先删缓存、再更新数据库
- 先更新数据库、再删除缓存
延时双删(先删缓存、再更新数据库)
延时双删的基本思路如下:
- 删除缓存;
- 更新数据库;
- sleep N毫秒;
- 再次删除缓存。
问题:采用读写分离的架构怎么办?
此时来了两个请求,请求 A(更新操作) 和请求 B(查询操作)
- 请求 A 更新操作,删除了 Redis;
- 请求主库进⾏更新操作,主库与从库进行同步数据的操作;
- 请 B 查询操作,发现 Redis 中没有数据;
- 去从库中拿去数据;
- 此时同步数据还未完成,拿到的数据是旧数据;
解决方法: 如果是对Redis 进行填充数据的查询数据库操作,那么就强制将其指向主库进⾏查询。
利用消息队列进行删除的补偿(先更新数据库、再删除缓存)
先更新数据库,后删除缓存这⼀种情况也会出现问题,比如更新数据库成功了,但是在删除缓存的阶段出错了没有删除成功,那么此时再读取缓存的时候每次都是错误的数据了。
此时解决方案就是利用消息队列进行删除的补偿。具体的业务逻辑⽤语⾔描述如下:
- 请求 线程A 先对数据库进行更新操作;
- 在对 Redis 进行删除操作的时候发现报错,删除失败;
- 此时将Redis 的 key 作为消息体发送到消息队列中;
- 系统接收到消息队列发送的消息后再次对 Redis 进行删除操作;
上面方案的优化
Canal:基于数据库增量日志解析,提供增量数据订阅和消费https://github.com/alibaba/canal
mysql会将操作记录在Binary log日志中,通过canal去监听数据库日志二进制文件,解析log日志,同步到redis中进行增删改操作。
canal的工作原理:canal 模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,向 MySQL master 发送dump 协议;MySQL master 收到 dump 请求,开始推送 binary log 给 slave (即 canal );canal 解析 binary log 对象(原始为 byte 流)。