如果一个数据最先进入缓存中,则应该最早淘汰掉
实现思路也是很简单的, 套用消息队列思路, 每次新生成缓存标记放到队列尾部, 优先淘汰队列头部的数据.
优点: 实现简单, 耗费资源少 缺点: 根据加入时间越早越 淘汰, 如果属于热门数据, 将被反复淘汰、加入, 降低缓存命中率
最不经常使用,如果一个数据在最近一段时间内使用次数很少,那么在将来一段时间内被使用的可能性也很小
这种方式解决了 FIFO 模式的对于热门数据的劣势, 在实现上按照访问次数进行排列, 需要维护每个记录的访问次数.
优点: 大部分场景提高缓存命中率 劣势: 实现上内存消耗大, 某些场景例如秒杀数据, 短时期内访问数增长奇高, 但之后没有访问, 但根据此算法很难短时间内过期.
最近最少使用,如果数据最近被访问过,那么将来被访问的几率也更高
相对于仅考虑时间因素的 FIFO 和仅考虑访问频率的 LFU,LRU 算法可以认为是相对平衡的一种淘汰算法
实现方式也很简单, 维护一个队列, 如果某条记录被访问了,则移动到队尾,那么队首则是最近最少访问的数据,淘汰该条记录即可
优点: 实现简单, 解决了 FIFO 模式的一成不变也解决了 LFU 内存消耗、过期问题 缺点: 特殊场景下, 比如偶发现批量访问非热点缓存, 有导致热点数据被移除风险.
实现方式: 更新db后将 cache 删除, cache中没有数据则读db回种到 cache
优点: 实现简单, 降低了缓存不一致的概率
缺点: 增加业务系统压力, 需要维护db、cache两个数据源, 增大了数据库压力, 并且如果为主从查询模式, 有数据不一致风险.
实现方式: 单独实现存储服务, 业务方只关注存储服务即可. 更新数据如果存在cache则更新后再更新db, 如果不存在cache只更新db. 读取数据存在cache则返回, 不存在从db获取后回种cache返回
优点: 封装处理细节, 数据有冷热区分, 内存利用效率高
缺点: 原文给出的方案是先更新cache再更新db, 本人猜测可能防止读取过程中出现不一致情况, 但具体情况具体分析, 比如更新DB失败情况.
实现方式: 只更新缓存不更新数据库, 定期同步到数据库
优点: 当请求量大时, 比如计数器 批量写入很好的缓解了db的压力, 提高响应能力
缺点: 存在丢失数据风险
大量缓存失效可能引发缓存雪崩问题(也有文章将此类问题归纳为缓存雪崩)
数据不存在导致一直回种失败, 大量请求影响系统稳定
缓存某节点负载过高不可用, 导致rehash到另一个节点同样难以承受, 出现连续问题(也有文章将大量缓存集中过期视为雪崩, 主要看对系统产生足够影响)
DB与数据同一时刻不一致、缓存多副本不一致
也有文章将此称为缓存击穿, 是指一个热点缓存正好过期, 多个进程或线程同时查询数据库回种缓存, 导致数据库压力增大
Hot key, 因突发事件导致的热点key被打到一个缓存节点机器上, 被打到物理网卡、带宽、CPU 的极限,从而导致缓存访问变慢、卡顿
Big key, 部分key的value过大, 读写超时, 耗费资源高, 影响正常其他key