Skip to content

策略

内存淘汰超时剔除主动更新
说明不用自己维护,利用 Redis 的内存淘汰机制,当内存不足时自动淘汰部分数据,下次查询时更新缓存。给缓存数据添加 TTL 时间,到期后自动删除缓存,下次查询时更新缓存。编写业务逻辑,在修改数据库的同时,更新缓存。
一致性一般
维护成本

低一致性需求:使用内存淘汰机制,例如店铺类型的查询的缓存。

高一致性需求:主动更新,并以超时剔除作为兜底方案,例如店铺详情查询的缓存。

读操作

  • 缓存命中直接返回

  • 缓存未命中则查询数据库,并写入缓存,设置超时时间。

写操作

  • 先写数据库,再删除缓存。

  • 要确保数据库和缓存操作的原子性

主动更新

  • 由缓存的调用者,在更新数据库的同时更新缓存,实际中使用最多。

  • 缓存与数据库整合为一个服务,由服务来维护一致性。调用者调用该服务,无需关心缓存一致性 问题。

  • 调用者只操作缓存,由其它线程异步的将缓存数据持久化到数据库,保证最终一致。

操作缓存与数据库时需要考虑三个问题:

  • 删除缓存还是更新缓存

    更新缓存:每次更新数据库时都更新缓存,导致无效写操作较多,比如更新了 100 次,需要写 100 次,如果没有访问,会导致无效写操作.

    删除缓存:每次更新数据库时让缓存失效,查询时再更新缓存,比如更新了 100 次,只需要删 1 次,查询时再更新缓存。因此一般选择删除缓存。

  • 如何保证缓存与数据库的操作同时成功或失败

    单体系统:将缓存与数据库操作放在一个事务

    分布式系统:利用 TTC 等分布式事务方案

  • 先删除缓存还是先更新数据库

    线程 1 负责删除缓存再更新数据库,删除缓存后线程 2 正好查询缓存,未命中, 去查询数据库,此时线程 1 还没能够更新数据库,导致线程 2 将数据库内容写入缓存,之后 线程 1 才更新数据库,导致缓存不一致。

    线程 1 负责更新数据库再删除缓存,线程 2 由于缓存过期正好来查询缓存,未命中, 去查询数据库,查询到旧的数据,此时线程 1 更新数据库并删除缓存,之后线程 2 写入缓存, 导致缓存不一致,这种的触发条件比较苛刻,因此先更新数据库再删除缓存。