过期时间相关命令:
expire key seconds:设置key的过期时间
ttl key:查看key的过期时间
persist key:删除key的过期时间
过期策略:
惰性删除[被动,零散处理]:是在客户端访问这个 key 的时候,redis 对 key 的过期时间进行检查,如果过期了就立即删除。
定时删除[主动,集中处理]:会将每个设置了过期时间的 key 放入到一个独立的字典中,以后会定时遍历这个字典来删除到期的 key。
过期策略-定时删除:
算法:贪心算法
频率:默认1s10次,每次不超过25ms(CPU时间的25%)[防止阻塞用户请求]
过程:
1.从过期字典(保存了所有key过期时间的字典)中随机 20 个 key;
2.删除这 20 个 key 中已经过期的 key;
3.如果过期的 key 比率超过 1/4,那就重复步骤 1;
(面试题)Redis的大key会不会有什么问题?对Redis的影响是什么?
大Key:BigKey,指Value比较大(数据过大、成员过多)的Key。
一个STRING类型的Key,它的值为5MB(数据过大)
一个LIST类型的Key,它的列表数量为20000个(列表数量过多)
一个ZSET类型的Key,它的成员数量为10000个(成员数量过多)
一个HASH格式的Key,它的成员数量虽然只有1000个但这些成员的value总大小为100MB(成员体积过大)
造成的问题:
1.占用过多的内存、可能触发内存淘汰策略,重要的key被驱逐或者阻塞写入
2..读取占用服务器网络带宽
3.删除一个大Key会造成Redis较为长时间的阻塞
string的底层实现SDS,释放(sdsfree)的时间复杂度为O(N),N为长度
hash的底层实现hashtable,释放(dictRelease)的时间复杂度为O(N),N为键值对数量
list的底层实现quicklist,释放(quicklistRelease)的时间复杂度O(N),N为成员数量
zset的底层实现skiplist,释放(zslFree)的时间复杂度为O(N),N为长度。
如何发现BigKey?
redis自带工具:redis-cli --bigkeys
如何解决BigKey?
1.通过redis自带工具发现BigKey,查看是否符合业务场景,若不符合,则在业务层避免。
2.是否能够使用其他NoSQL,若可以,则使用。
3.若无法避免,则应避免阻塞Redis用户线程,需要释放BigKey时,应用程序使用unlink异步释放空间,不阻塞Redis用户线程。
最大内存淘汰策略:指Redis的内存使用到达了配置的最大限制,如何淘汰内存中的key的策略。
redis的内存大小限制在redis.conf中配置
maxmemory <bytes>:最大内存限制,默认64位系统不限制内存,32位系统最多使用3GB内存
maxmemory-policy <策略名称>:淘汰策略
淘汰策略:(没有优劣,看场景)
volatile-lru:从已设置过期时间的数据集中挑选最近最少使用的数据淘汰。
volatile-ttl:从已设置过期时间的数据集中挑选将要过期的数据淘汰。
volatile-random:从已设置过期时间的数据集中任意选择数据淘汰。
allkeys-lru:从数据集中挑选最近最少使用的数据淘汰。
allkeys-random:从数据集中任意选择数据淘汰,当内存达到限制的时候,对所有数据集挑选随机淘汰,直到可写入新的数据集。
no-enviction:当内存达到限制的时候,不淘汰任何数据,不可写入任何数据集,所有引起申请内存的命令会报错。(常用)
淘汰过程:
客户端发起了需要申请更多内存的命令(如set)。
Redis检查内存使用情况,如果已使用的内存大于maxmemory则开始根据用户配置的不同淘汰策略来淘汰内存(key),从而换取一定的内存。
如果上面都没问题,则这个命令执行成功。否则客户端报错
查看Redis内存使用情况:info指令
RDB:快照,指在指定的时间间隔内将内存中的数据集快照写入磁盘。默认为dump.rdb
AOF: append-only file 会将每一个收到的写命令都通过write函数追加到文件中。默认为appendonly.aof
RDB的相关配置(redis.conf):
RDB的执行过程:
优点: 文件小,适合备份 恢复速度快
缺点: 宕机时,丢失的数据多(全量快照部分自然不能运行太频繁) 需要通过fork子进程方式协助完成持久化,数据量较大时,可能会造成阻塞。
手工指令:
save:同步生成RDB文件
bgsave:异步生成RDB文件
AOF的相关配置(redis.conf):
AOF的执行过程:
优点: 不易丢失数据
缺点: 体积较大
手工指令:
bgrewriteaof:异步重写aof文件
(面试题)当不小心执行了FLUSHALL命令,如何恢复Redis数据?
思路:利用redis的aof文件
步骤:
1.关闭redis服务,shutdown nosave
2.找到aof文件,去除flushall命令的那一行
3.启动redis服务
在Redis4.0提供了RDB和AOF的混合持久化策略
执行过程:RDB、AOF的执行过程不变,只是RDB的快照覆盖写入AOF文件,到达了“RDB做全量,AOF做增量”的效果