Redis过期策略
定期删除:Redis 默认是每隔 100ms 就随机抽取一些设置了过期时间的 key,检查其是否过期,如果过期就删除
惰性删除:获取某个 key 的时候,Redis 会检查一下 ,这个 key 如果设置了过期时间那么是否过期了?如果过期了此时就会删除,不会给你返回任何东西。
内存淘汰机制: 当Redis的内存使用达到限制时:
- noeviction:新写入操作会报错(很少使用,因为无法预估)。
- allkeys-lru:移除最近最少使用的 key(最常用)。
- allkeys-random:在键空间中,随机移除某个 key。(很少使用)
- volatile-lru:在设置了过期时间的键空间中,移除最近最少使用的 key。
- volatile-random:在设置了过期时间的键空间中,随机移除某个 key。
- volatile-ttl:在设置了过期时间的键空间中,有更早过期时间的 key 优先移除。
LRU算法:最近最少使用
LRU(Least Recently Used)算法是一种经典的缓存替换策略,它的核心思想是优先淘汰最近最少使用的数据,以便为新数据腾出空间。在数据缓存场景中,LRU算法能够保留热门数据,从而提高缓存的命中率。
LRU算法的原理非常直观:当缓存空间满了,系统会优先淘汰最久未被访问的数据。这个策略的背后思想是,如果某个数据在最近一段时间内没有被访问,那么它在未来也可能不会被访问。这种替换策略有助于保持缓存中的数据是热数据
,即最近被频繁访问的数据。
优点:
优点 | 描述 |
---|---|
适用于热数据 | LRU算法保留了最近最常访问的数据,因此非常适用于具有明显访问热点的场景。 |
简单有效 | LRU算法的实现相对简单,不需要复杂的计算和维护。 |
限制:
限制 | 描述 |
---|---|
周期性访问 | LRU算法可能会因为数据的周期性访问而导致不必要的数据替换,特别是在某些特殊业务场景中。 |
缓存污染 | LRU算法容易受到突发的大量访问影响,可能导致缓存中的“热·数据被淘汰,从而影响缓存效果。 |
基于 LinkedHashMap 的LRU
public class LRU<K, V> extends LinkedHashMap<K, V> {
private int capacity;
/**
* 传递进来最多能缓存多少数据
*
* @param capacity 缓存大小
*/
public LRUCache(int capacity) {
super(capacity, 0.75f, true);
this.capacity = capacity;
}
/**
* 如果map中的数据量大于设定的最大容量,返回true,再新加入对象时删除最老的数据
*
* @param eldest 最老的数据项
* @return true则移除最老的数据
*/
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
// 当 map中的数据量大于指定的缓存个数的时候,自动移除最老的数据
return size() > capacity;
}
}
LFU算法:最不经常使用
LFU(Least Frequently Used)算法是一种与LRU相似的缓存替换策略,它的核心思想是优先淘汰最不经常使用的数据,以便为新数据腾出空间。在某些特定场景下,LFU算法能够更好地适应数据访问模式的变化。
优点
优点 | 描述 |
---|---|
适用于频繁刷新 | LFU算法能够优先保留频繁被刷新的数据,适合某些周期性访问的场景。 |
对数据热度变化敏感 | 相比于LRU算法,LFU算法更能适应数据访问模式的变化,能够更好地反映数据的热度。 |
限制
限制 | 描述 |
---|---|
计算复杂性 | LFU算法需要维护数据的访问频率记录,这可能导致一定的计算复杂性,特别是在大规模数据场景下。 |
冷启动问题 | 对于刚开始访问的数据,由于没有足够的访问频率信息,LFU算法可能难以做出合适的替换决策。 |
Random Replacement(随机替换)
随机替换是一种简单但有效的缓存策略。与LRU和LFU不同,随机替换策略不考虑数据的访问时间或频率,而是随机选择要替换的数据。尽管这听起来不太智能,但在某些场景下,随机替换策略表现出意外的优势。
随机替换的核心思想是,每次需要替换数据时,从缓存中随机选择一条数据进行替换。虽然这种策略没有考虑数据的热度或频率,但在一些特殊情况下,随机替换能够避免特定数据被频繁淘汰,从而维持一定的数据多样性。
Least Recently Used with Sampling(LRUS)
除了传统的LRU算法,还存在一种改进的版本,即LRUS(Least Recently Used with Sampling)算法。LRUS算法通过周期性的采样来记录数据的访问情况,从而更好地估计最近使用的数据,减少了LRU算法中的“冷启动·问题。
LRUS算法引入了采样机制,通过周期性地记录一部分数据的访问情况,从而更准确地判断哪些数据是热数据,哪些是冷数据。与传统的LRU算法不同,LRUS算法能够更好地适应数据访问模式的变化,提高数据缓存的命中率。
实例
商品列表页:由于商品列表页中的商品信息经常变动,可以选择LRU(最近最少使用)或者随机替换策略。这样可以保留最近的商品数据,提高页面加载速度。
商品详情页:商品详情页的数据相对稳定,适合选择LFU(最不经常使用)策略。这样可以保留频繁访问的商品详情数据,提高页面响应速度。
购物车页:购物车页的数据与用户关联紧密,可以选择LRU(最近最少使用)或者LRUS(最近最少用于采样)策略。这样可以保留最近被访问的购物车数据,提供更好的用户体验。
总结
在实际应用中,选择合适的缓存策略是至关重要的。根据不同的业务场景和数据访问模式,我们可以灵活地选择LRU、LFU、LRUS、随机替换等缓存策略。同时,还可以根据实际需要动态地调整缓存大小,以达到最佳的性能与资源利用率的平衡。
分析数据访问模式:在选择缓存策略之前,首先需要详细分析数据的访问模式。哪些数据被频繁访问?哪些数据变化较少?根据这些信息,选择适合的缓存策略。
选择合适的算法:根据业务需求,选择合适的缓存算法。LRU适用于保留最近访问的数据,LFU适用于保留最频繁访问的数据,而LRUS则更好地应对访问模式的变化。
监控与优化:缓存策略不是一成不变的,需要不断监控数据访问情况,优化缓存大小和策略。通过监控缓存的命中率和利用率,可以动态地做出调整。
灵活应用:不同的业务模块可能需要不同的缓存策略。根据实际情况,可以在系统中采用多种缓存策略,以最大程度地提升性能。
https://juejin.cn/post/7274146202496614458