目录
- 一、缓存更新策略
- 二、主动更新策略
- 三、Cache Aside Pattern
- 3.1 删除缓存还是更新缓存?
- 3.2 如何保证缓存与数据库的操作同时成功或失败?
- 3.3 先操作缓存还是先操作数据库
- 3.3.1 先删缓存再删库
- 3.3.2 先删库再删缓存
一、缓存更新策略
- 1.内存淘汰:不用自己维护,利用redis的内存淘汰机制,当内存不足时自动淘汰部分数据,下次查询时更新缓存,一致性差,没有维护成本
- 2.超时剔除:给缓存数据添加TTL时间,到期后自动删除缓存。下次查询时更新缓存,一致性一般,维护成本低
- 3.主动更新:编写业务逻辑,在修改数据库的同时,更新缓存,一致性好,维护成本高
- 4.低一致性需求可以使用内存淘汰机制
- 5.高一致性需求可以主动更新,并以超时剔除作为兜底方案
二、主动更新策略
- 1.Cache Aside Pattern 旁路缓存模式,在更新数据库的同时更新缓存
- 2.Read/Write Through Pattern 读写穿透模式,缓存与数据库整合为一个服务,由服务来维护一致性。调用者调用该服务,无需关心缓存一致性问题
- 3.Write Behind Caching Pattern 异步缓存写入模式,调用者只操作缓存,由其它线程异步的将缓存数据持久化到数据库,保证最终一致
三、Cache Aside Pattern
3.1 删除缓存还是更新缓存?
- 1.每次更新数据库都更新缓存,无效的写操作较多;
- 2.更新数据库让缓存失效,查询时再更新缓存更好
3.2 如何保证缓存与数据库的操作同时成功或失败?
- 1.单体系统中将缓存和数据库操作放在同一个事务中
- 2.分布式系统利用TCC (Try、Confirm、Cancel)等分布式事务方案
3.3 先操作缓存还是先操作数据库
- 1.先删缓存再删数据库
- 2.先删数据库再删缓存
- 3.先删数据库再删缓存比较好,这种发生的概率相对来说小一点,然后给缓存加上一个过期时间,一旦不一致时,缓存失效也再次查询数据库
3.3.1 先删缓存再删库
正常情况(示例)
- 1.有线程A和线程B操作缓存和数据库
- 2.线程A想把姓名改为张三,先删缓存,然后更新数据库,姓名是张三,执行完毕
- 3.线程B查询缓存,未命中,查询数据库,将张三写入缓存,拿到张三
- 4.此时数据库和缓存的数据都是张三
异常情况(示例)
- 1.有线程A和线程B操作缓存和数据库
- 2.线程A想把姓名李四改为张三,先删缓存,删除缓存成功,准备更新数据库为张三
- 3.线程B开始查缓存,未命中,查询数据库为李四,将李四写入缓存,执行完毕
- 4.线程A更新数据库为张三成功,执行完毕
- 5.此时数据库数据为张三,但缓存是李四
3.3.2 先删库再删缓存
正常情况(示例)
- 1.有线程A和线程B操作缓存和数据库
- 2.线程A想把姓名李四改为张三,先更新数据库,姓名改为张三,删除缓存,执行完毕
- 3.线程B查询缓存,未命中,查询数据库,将张三写入缓存,拿到张三
- 4.此时数据库和缓存的数据都是张三
异常情况(示例)
- 1.有线程A和线程B操作缓存和数据库
- 2.线程B查询缓存,未命中,查询数据库,拿到李四,还没来的及写入缓存
- 3.线程A想把姓名李四改为张三,先更新数据库,姓名改为张三,删除缓存,执行完毕
- 4.线程B将李四写入缓存,执行完毕
- 5.此时数据库数据为张三,缓存为李四