注:本文主要参考自《Redis设计与实现》 https://www.cnblogs.com/xuliangxing/p/7151812.html https://www.cnblogs.com/sunsing123/p/11093038.html http://www.imooc.com/article/257065?block_id=tuijian_wz
所谓过期,就是我们插入数据的时候设置了过期时间,一班情况下有下面两种设置g
具体的使用方式:查看"java企业项目开发实践"的第九章 企业项目开发--分布式缓存Redis(1)和第十章 企业项目开发--分布式缓存Redis(2)
注意:
对于上面咱们设置了过期时间的数据,那数据到期了咱们怎么删除呢?
slave的key不会过期,只会等待master的key过期
。如果master的key过期,或者通过LRU淘汰了key,那么会发送一条模拟的del命令给slave
如果当前库中没有一个key设置了过期时间,直接执行下一个库的遍历 随机获取一个设置了过期时间的key,检查该key是否过期,如果过期,删除key 判断定期删除操作是否已经达到指定时长,若已经达到,直接退出定期删除。
对于定期删除,在程序中有一个全局变量current_db来记录下一个将要遍历的库,假设有16个库,我们这一次定期删除遍历了10个,那此时的current_db就是11,下一次定期删除就从第11个库开始遍历,假设current_db等于15了,那么之后遍历就再从0号库开始(此时current_db==0) 由于在实际中并没有操作过定期删除的时长和频率,所以这两个值的设置方式作为疑问?
过期key对RDB没有任何影响
从内存数据库持久化数据到RDB文件
持久化key之前,会检查是否过期,过期的key不进入RDB文件
从RDB文件恢复数据到内存数据库
数据载入数据库之前,会对key先进行过期检查,如果过期,不导入数据库(主库情况)
过期key对AOF没有任何影响
从内存数据库持久化数据到AOF文件:
当key过期后,还没有被删除,此时进行执行持久化操作(该key是不会进入aof文件的,因为没有发生修改命令)
当key过期后,在发生删除操作时,程序会向aof文件追加一条del命令(在将来的以aof文件恢复数据的时候该过期的键就会被删掉)
AOF重写
重写时,会先判断key是否过期,已过期的key不会重写到aof文件
内存淘汰机制 Redis 的内存占用会越来越高。Redis 为了限制最大使用内存,提供了 redis.conf 中的配置参数 maxmemory。
当内存超出 maxmemory,Redis 提供了几种内存淘汰机制让用户选择,配置 maxmemory-policy:
不推荐
,使用这个策略,疯了吧)所有的 key
中,移除最少使用的key。只把 Redis 既当缓存是使用这种策略。(推荐
)。所有的 key
中,随机移除某个 key。(应该没人用吧)设置了过期时间 key
的字典中,移除最少使用的 key。把 Redis 既当缓存,又做持久化的时候使用这种策略。设置了过期时间 key
的字典中,随机移除某个key。设置了过期时间 key
的字典中,优先移除 ttl 小的,也就是移除马上就要过期的key。redis 中的默认的过期策略是volatile-lru 。设置方式 可以通过命令直接设置 config set maxmemory-policy xxxx(eg:volatile-lru)
实现 LRU 算法除了需要 key/value 字典外,还需要附加一个链表,链表中的元素按照一定的顺序进行排列。当空间满的时候,会踢掉链表尾部的元素。当字典的某个元素被访问时,它在链表中的位置会被移动到表头。所以链表的元素排列顺序就是元素最近被访问的时间顺序。
这里基于linkhashmap实现一个lru算法,可设置最大容量,淘汰最老的数据
class LRUCache<K, V> extends LinkedHashMap<K, V> {
private final int CACHE_SIZE;
public LRUCache(int size) {
//true代表顺序存放,最新的放头部,最老的放尾部
super((int) Math.ceil(size / 0.75) + 1, 0.75f, true);
CACHE_SIZE = size;
}
/**
* 定义移除最老的数据的规则
*
* @author zyh
* @date 2021/8/4
**/
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
return size() > CACHE_SIZE;
}
}
```t