Redis过期策略
做法:对键设置过期时间时,同步设置一个定时器,当达到定时时间时间时,立即删除键;优点:省内存,立即删除,释放内存;缺点:CPU使用率高,容易造成系统卡顿;Redis并不推荐的方式;
1、定时删除
做法:对键设置过期时间时,同步设置一个定时器,当达到定时时间时间时,立即删除键;
优点:省内存,立即删除,释放内存;
缺点:CPU使用率高,容易造成系统卡顿;
Redis并不推荐的方式;
2、惰性删除
做法:不主动删除key,在每次读写之前,调用expireIfNeeded函数确定key是否过期,如果过期删除,没有就不做处理,之后执行命令;
优点:直接删除效率大部分非常快,只有非常大的对象回收时可能存在卡顿,CPU处理次数少;
缺点:很多到了过期时间的key还占用着内存;
内存够多,不存在非常多设置了失效时间的大对象可以使用;
3、定期删除
做法:定时删除和定期删除的折中做法,把设置了过期时间的key放入一个特定的字典中,周期性调用activeExpireCycle函数,周期时间可以设定,默认100ms执行一次,从特定的某个库开始轮训,db0,db1…,保证每一个redis的库都被执行到,随机选出一定量的key,删除达到了过期时间的key,并判断删除的key是否大于某一个值,比如1/4,如果超过1/4,则表示有很多的key需要失效,重复随机选择key,删除key操作,知道删除的key小于1/4;
优点:省内存对CPU执行大概率也不会非常频繁;
缺点:可能存在过期的key被使用,如果一段时间非常多的key失效,导致循环次数过多,也会造成系统卡顿;
一般推荐方式;
3.1、定期删除为什么不扫描所有key
如果过期的key过多,扫描时间和删除时间过大,如果多次大于1/4,系统就会一直卡死,导致客户端查询一直不可用,所以Redis为每次扫描设置了扫描上限时间,默认25ms,这样也就不能扫描所有的key,时间上不够;
3.2、为什么不建议多个失效key使用相同的时间,而是使用随机时间
多个key同时失效,删除会一直循环,系统卡住,而且多个key同时失效,会造成缓存雪崩,大量的查询直接查询数据库,最后导致数据库性能急剧下降;
3.3、为什么Redis设置了扫描上限时间25ms,还是会出现卡顿
因为Redis执行指令是单线程,循环次数过多,每次25ms,100次就是2.5s,所以会存在卡顿;
4、异步删除策略,这样就不会阻碍主线程的操作
unlink 指令,它能对删除操作进行懒处理,丢给后台线程来异步回收内存。
unlink key
flushall 清理数据库
flushdb async
flushall async
从库接受完 rdb 文件后的 flush 操作
slave-lazy-flush
内存达到 maxmemory 时进行淘汰
lazyfree-lazy-eviction
过期删除
lazyfree-lazy-expire key
指令删除 destKey
lazyfree-lazy-server-del rename
5、设置了内存最大值,需要同步设置内存淘汰侧率
noeviction:当内存超出 maxmemory,写入请求会报错,但是删除和读请求可以继续,业务上基本不能使用。
allkeys-lru:当内存超出 maxmemory,在所有的 key 中,移除最少使用的key,只把 Redis既当缓存时可以使用这种策略。
allkeys-random:当内存超出 maxmemory,在所有的 key 中,随机移除某个 key,过于危险,不可控。
volatile-lru:当内存超出 maxmemory,在设置了过期时间 key 的字典中,移除最少使用的 key。把 Redis既当缓存,又做持久化的时候使用这种策略。
volatile-random:当内存超出 maxmemory,在设置了过期时间 key 的字典中,随机移除某个key。
volatile-ttl:当内存超出 maxmemory,在设置了过期时间 key 的字典中,优先移除 ttl 小的。
6、Redis的近似LRU和LFU算法
LRU算法:删除最近使用时间最早的数据;
逻辑:维持一个按照最近访问时间的双向链表,内存达到最大值,循环移除链表后面的数据,直到内存小于最大值,如果key被访问,把当前key放在链表头部,当一个只访问过一次的key,它被淘汰删除的时间会很长;
LFU算法:在一段时间内访问最少的key最先删除;
逻辑:每一个key保存访问次数;
// redis 的对象头
typedef struct redisObject {
unsigned type:4; // 对象类型如 zset/set/hash 等等
unsigned encoding:4; // 对象编码如 ziplist/intset/skiplist 等等
unsigned lru:24; // 对象的「热度」
int refcount; // 引用计数
void *ptr; // 对象的 body
} robj;
Redis在内存大于设定的最大值时,根据配置的过期算法和策略,获取key信息,之后根据Redis对象的头部信息,判断使用时间和次数,根据具体的算法删除数据。
7、Redis持久化RDB(Redis DataBase)和AOF(Append Only File)
RDB:根据指定的时间做持久化,默认方式,redis.conf配置路径,生成dump.rdb二进制文件;
方式:启动一个子进程,子进程有父进程的内存快照,在持久化过程中,父进程修改内容,子进程不能感知,每次备份都是全量备份;
优点:可以在Redis空闲的时候持久化,还原速度快; 缺点:服务宕机,只能恢复上次持久化的数据,指定持久化时间越短,需要更多的存储空间;
AOF:保存所有的对Redis做更新的命令到磁盘,还原时重新执行一次所有的更新炒作;
方式:Redis将执行完的命令、命令的参数、命令的参数个数等信息发送到AOF程序中,AOF程序根据接收到的命令数据,将命令转换为网络通讯协议的格式,然后将协议内容追加到服务器的AOF缓存中,AOF缓存中的内容被写入到AOF文件末尾,如果设定的AOF保存条件被满足的话,fsync函数或者fdatasync函数会被调用,将写入的内容真正地保存到磁盘中。
优点:恢复时数据保存完整; 缺点:恢复数据慢,而且每次更新操作都持久化,少量命令,耗时可控,批量命令,大对象,性能降低;
7.1AOF需要手动开启,RDB默认开启,开启方式
# 可以通过修改redis.conf配置文件中的appendonly参数开启
appendonly yes
# AOF文件的保存位置和RDB文件的位置相同,都是通过dir参数设置的。
dir ./
# 默认的文件名是appendonly.aof,可以通过appendfilename参数修改
appendfilename appendonly.aof
更多推荐
所有评论(0)