Redis灵魂拷问系列之过期策略与数据持久化
1.redis过期策略能说一下吗
1.1 redis为什么需要过期策略
我们平常用 redis 做缓存时,可能会有一些问题:为什么有的key塞入之后就会消失,如果真的发现这样的情况,说明可能 redis 没有用对。
redis 本质上属于 内存数据库,把内存当作缓存使用,可以从图中看出,内存属于 ns 级别,可见速度是很快的。但是内存也是宝贵的,可以从几千的电脑只有 那么16、32G的内存,而可以有1T的硬盘中看出。
当内存被你不断塞入的数据给塞满,那么 redis 就会在你再次塞入数据时根据一些算法(LRU、LFU等)给你淘汰一些数据,才能保证你能存入数据
1.2 定期删除、惰性删除
redis使用 定期删除 + 惰性删除 的方式淘汰过期数据
- 定期删除:redis在定期删除(比如100ms)时,不会每次都把过期的key全部删除,而是随机抽取一些过期数据进行删除
- 惰性删除:当过期数据被访问时,redis 会进行检查,如果过期则进行删除
但是这样还是会有一些问题,如果过期数据定期删除时一直未被删除,又一直未被查询导致不走惰性删除,那么还是会一直占据着内存空间,最终导致内存占满。redis 使用 内存淘汰机制 来处理这一问题。
1.3 内存淘汰机制
redis在内存占用过多时,会自行使用一些淘汰算法,淘汰一些数据
- allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 key(这个是最常用的)
- volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的 key(这个一般不太合适)
- volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的 key 优先移除
- noeviction: 当内存不足以容纳新写入数据时,新写入操作会报错(很少用)
- allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个 key(很少用)
- volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个 key(很少用)
1.4 可以手写一个LRU算法吗
我们可以基于Java的数据结构 LinkedHashMap 来写一个
大致思路:创建LRUCache类,继承LinkedHashMap类,定义一个存放数据数量的阈值,编写构造器方法,使用LinkedHashMap类的构造器方法,设置初始容量、负载因子以及按访问顺序排序(true),重写removeEldestEntry()
方法,设置当容量超过阈值时,会把最少访问的数据删除
class LRUCache<K, V> extends LinkedHashMap<K, V> {
private final int CACHE_SIZE;
/**
* 传递进来最多能缓存多少数据
*
* @param cacheSize 缓存大小
*/
public LRUCache(int cacheSize) {
// true 表示让 linkedHashMap 按照访问顺序来进行排序,最近访问的放在头部,最老访问的放在尾部。
super((int) Math.ceil(cacheSize / 0.75) + 1, 0.75f, true);
CACHE_SIZE = cacheSize;
}
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
// 当 map中的数据量大于指定的缓存个数的时候,就自动删除最老的数据。
return size() > CACHE_SIZE;
}
}
2.redis持久化RDB和AOF
也不妨瞧瞧官方怎么说的:REDIS persistence
【参考链接】
1:Redis 核心篇:唯快不破的秘密
2:Redis 6.0 新特性-多线程连环13问!
3:redis中文官方网站
4:redis 数据持久化-官方网站