数据库缓存一致性问题
https://xiaolincoding.com/redis/architecture/mysql_redis_consistency.html#%E5%B0%8F%E7%BB%93
小林写的很全面,我基于此做了 xmind 加深印象
# 数据库缓存一致性问题
# 先更新数据库,再删除缓存(Cache Aside 策略)
# 读策略
- 如果读取的数据命中了缓存,则直接返回数据;如果读取的数据没有命中缓存,则从数据库中读取数据,然后将数据写入到缓存,并且返回给用户
# 写策略
- 更新数据库中的数据;删除缓存中的数据。
# 因为缓存的写入通常要远远快于数据库的写入,所以在实际中很难出现请求 B 已经更新了数据库并且删除了缓存,请求 A 才更新完缓存的情况
# 对缓存的命中率带来影响
# 先删除缓存,再更新数据库
# 延迟双删
#删除缓存 redis.delKey(X) #更新数据库 db.update(X) #睡眠 Thread.sleep(N) #再删除缓存 redis.delKey(X)
# 先更新数据库,再更新缓存
# 先更新缓存,再更新数据库
# 如何保证两个操作都能执行成功?
# 引入消息队列
# 订阅 MySQL binlog,再操作缓存
「先更新数据库,再删缓存」的策略的第一步是更新数据库,那么更新数据库成功,就会产生一条变更日志,记录在 binlog 里。
于是我们就可以通过订阅 binlog 日志,拿到具体要操作的数据,然后再执行缓存删除,阿里巴巴开源的 Canal 中间件就是基于这个实现的。
Canal 模拟 MySQL 主从复制的交互协议,把自己伪装成一个 MySQL 的从节点,向 MySQL 主节点发送 dump 请求,MySQL 收到请求后,就会开始推送 Binlog 给 Canal,Canal 解析 Binlog 字节流之后,转换为便于读取的结构化数据,供下游程序订阅使用。