使用 Redis 作为 MySQL 的前置缓存时,需要注意的问题
要考虑是先更新缓存、再更新数据库,还是先更新数据库、再更新缓存,是更新缓存还是删除缓存,这些情况很多会因为 2 个进程因为处理速度、网络速度问题导致脏数据的情况发生;
要保证最终一致性,其实使用 redis 的 ttl 即可,第一次修改后设置小点的 ttl,下次又会再更新,因为本身脏数据出现的机率就很小(尤其先更新数据库再删除缓存形式),多次更新最终肯定是正确的值。下面是使用 二次删除 + 异步延迟删除模式达到比较好的更新数据效果,同时和程序代码解耦;
使用 二次删除 + 异步延时删除策略
- 更新数据库数据
- 数据库将操作信息写入 binlog 日志当中
- 订阅程序(Canal、Maxwell、FlinkCDC 等)提取出所需要的数据以及 key
- 另起一段非业务代码,获取该信息
- 尝试删除缓存操作,如果正确删除了,过几百毫秒(考虑一次数据库写入的最大可能时间长度在增加一些毫秒数)后再次删除缓存(可以在非业务代码中 sleep,也可以放入消息队列中,再取一遍)
- 如果发现删除失败,将这些信息发送到消息队列中
- 非业务代码重新从消息队列中获取数据,重试删除操作