1. 理解淘汰机制
1.1. 内存回收策略
Redis内存回收机制主要体现在以下两个方面:
1. 删除到达时间的键对象。
2. 内存使用达到maxmemory上限时触发内存溢出控制策略。
1.1.1. 删删除除过过期期键键对对象
Redis所有的键都可以设置过期属性,内部保存在过期字典中。由于进程内保存了大量的键,维护每个键精准的过期删除机制会导致消耗大量的CPU,对于单线程的 Redis来说成本过高,因此Redis采用惰性删除和定时任务删除机制实现过期键的内存回收 。
- 惰性删除:惰性删除用于当客户端读取带有超时属性的键时,如果已经超过键设置的过期时间,会执行删除操作并返回空,这种策略是出于节省CPU成本 考虑,不需要单独维护TTL链表来处理过期键的删除。但是单独用这种方式存在内存泄露的问题,当过期键一直没有访问将无法得到及时删除,从而导致内 存不能及时释放。正因为如此,Redis还提供另一种定时任务删除机制作为惰性删除的补充。
- 定时任务删除:Redis内部维护一个定时任务,默认每秒运行10次(通过配置hz控制)。定时任务中删除过期键逻辑采用了自适应算法,根据键的过期比 例,使用快慢两种速率模式回收键。
流程说明:
1. 定时任务在每个数据库空间随机检查20个键,当发现过期时删除对应的键。
2. 如果超过检查数25%的键过期,循环执行回收逻辑直到不足25%或运行超时为止,慢模式下超时时间为25ms。
3. 如果之前回收键逻辑超时,则在Redis触发内部事件之前再次以快模式运行回收过期键任务,快模式下超时时间为1ms4且2s内只能运行1次。
4. 快慢两种模式内部删除逻辑相同,只是执行的超时时间不同
1.1.2. 内内存存溢溢出出控控制制策策略略
当Redis所用内存达到maxmemory上限时会触发相应的溢出控制策略。具体策略受maxmemory-policy参数控制,Redis支持6种策略
1. noeviction:默认策略,当内存不足以容纳新写入数据时,新写入操作会报错。应该没人用吧。
2. allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 Key。推荐使用,目前项目在用这种。
3. allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个 Key。应该也没人用吧,你不删最少使用 Key,去随机删。
4. volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的 Key。这种情况一般是把 Redis 既当缓存,又 做持久化存储的时候才用。不推荐。
5. volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个 Key。依然不推荐。
6. volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的 Key 优先移除。不推荐。如果没有对应的键,则 回退到noeviction策略。
我们通过配置redis.conf中的maxmemory这个值来开启内存淘汰功能。
* maxmemory : 值得注意的是,maxmemory为0的时候表示我们对Redis的内存使用没有限制
* maxmemory-policy noeviction :配置淘汰策略
* config set maxmemory-policy {policy} :动态配置淘汰策略
如如何何选选择择淘淘汰汰策策略略
下面看看几种策略的适用场景
allkeys-lru :如果我们的应用对缓存的访问符合幂律分布,也就是存在相对热点数据,或者我们不太清楚我们应用的缓存访问分布状况,我们可以选择 allkeys-lru策 略
allkeys-random :如果我们的应用对于缓存key的访问概率相等,则可以使用这个策略。
volatile-ttl:这种策略使得我们可以向Redis提示哪些key更适合被eviction
另外,volatile-lru策略和volatile-random策略适合我们将一个Redis实例既应用于缓存和又应用于持久化存储的时候,然而我们也可以通过使用两个Redis实例来达 到相同的效果,值得一提的是将key设置过期时间实际上会消耗更多的内存,因此我们建议使用allkeys-lru策略从而更有效率的使用内存 注意:频繁执行回收内存成本很高,主要包括查找可回收键和删除键的开销,如果当前redis有从节点,回收内存操作对应的删除命令会同步到从节点,导致写放大 的问题
2. 持久化
持久化的功能:Redis是内存数据库,数据都是存储在内存中,为了避免进程退出导致数据的永久丢失,需要定期将Redis中的数据以某种形式(数据或命令) 从内 存保存到硬盘。当下次Redis重启时,利用持久化文件实现数据恢复。除此之外,为了进行灾难备份,可以将持久化文件拷贝到一个远程位置。Redis持久化 分为 RDB持久化和AOF持久化,前者将当前数据保存到硬盘,后者则是将每次执行的写命令保存到硬盘。
2.1. RDB持久化
RDB是一种快照存储持久化方式,具体就是将Redis某一时刻的内存数据保存到硬盘的文件当中,默认保存的文件名为dump.rdb,而在Redis服务器启动时,会 重新 加载dump.rdb文件的数据到内存当中恢复数据。,触发 RDB 持久化过程分为手动触发和自动触发。
/ # find / -name *.rdb
/dump.rdb
/redis/data/dump.rdb
我们可以通过如下命令查看信息
RDB持久化功能所生成的RDB文件是一个经过压缩的二进制文件,通过该文件可以还原生成RDB文件是的数据库状态
触发机制
手动触发分别对应 save 和 bgsave 命令
save 命令:阻塞当前 Redis 服务器,直到 RDB 过程完成为止,对于内存比较大的实例会造成长时间阻塞,线上环境不建议使用。
bgsave 命令:Redis 进程执行 fork 操作创建子进程,RDB 持久化过程由子进程负责,完成后自动结束。阻塞只发生在 fork 阶段,一般时间很短。显然 bgsave 命令是针对 save 阻塞问题做的优化。因此 Redis 内部所有的涉及 RDB 的操作都采用 bgsave 的方式
除了执行命令手动触发之外,Redis 内部还存在自动触发 RDB 的持久化机制,例如以下场景:
1. 使用 save 相关配置,如“save m n”。表示 m 秒内数据集存在 n 次修改时,自动触发 bgsave。
2. 如果从节点执行全量复制操作,主节点自动执行 bgsave 生成 RDB 文件并发送给从节点。
3. 执行 debug reload 命令重新加载 Redis 时,也会自动触发 save 操作。
4. 默认情况下执行shutdown命令时,如果没有开启 AOF 持久化功能则自动执行 bgsave
2.2. AOF持久化
AOF(append only file)持久化:与RDB存储某个时刻的快照不同,AOF持久化方式会记录客户端对服务器的每一次写操作命令到日志当中,并将这些写操作 以 Redis协议追加保存到以后缀为aof文件末尾
开启 AOF 功能需要设置配置:appendonly yes,默认不开启。AOF 文件名通过 appendfilename 配置设置,默认文件名是 appendonly.aof。保存路径同 RDB 持久 化方式一致,通过 dir 配置指定
参数说明
演示
docker run -itd -v /redis_2004/masterandslave/slave:/redis -p 6389:6379 --network=redis5sm --ip=192.160.1.189 --name redis5slave redis5asm ps
修改配置 /redis/conf/redis.conf
appendonly yes
appendfilename "appendonly.aof"
然后测试
2.3. 混合持久化及持久化数据恢复
在redis5.0下默认就是开启了这个模式通过配置 aof-use-rdb-preamble
该模式并不会影响到正常的命令备份,仅仅只是影响到 aof模式的文件重写的;
主要是对于aof的一个补充;因为aof的流程中对于redis所有数据库中的内容读取并重写为命令,而重写的过程中会存在这命令写入的可能,aof的处理是先放在缓冲 区中积累,由子进程重写回收,主进程会通过管道的方式发送给子进程并直到子进程结束;但是子进程结束之后也还是会存在没有写入的命令,就会被回收;父进程用来积累命令使用的结构体,如果服务端执行一条命令时正在执行aof重写,命令还会同步到aof_rewrite_buf_blocks中这是一个list类型的缓冲区;
实现
在同时启用了RDB和AOF方法后,并且 aof-use-rdb-preamble 设置为yes,在重写AOF文件时,Redis首先会把数据集以RDB的格式转储到内存中并作为AOF文件的 开始部分。在重写之后, Redis继续使用传统的AOF格式在AOF文件中记录写人命令。你可以通过观察重写后的AOF文件头部和尾部清楚地了解这种混合格式。如果 启用了混合持久化,那么在AOF文件的开头首先使用的是RDB格式。因为RDB的压缩格式可以实现更快速地重写和加载数据文件,同时也保留了AOF数据一致性更 好的优点,所以Redis可以从混合持久化中获益。
数据恢复演示
首先确保持久化aof的配置关闭,先演示根据与rdb恢复数据
可以使用DEBUG POPULATE命令添加测试数据(aof不会检测到添加的数据)
注意如果说配置了, appendonly 为yes;redis在每次启动的时候就会去检测是否存在这个文件
需需要要额额外外注注意意::在在redis4及及以以上上的的版版本本中中即即时时存存在在RDB文文件件开开起起了了aof也也不不会会加加载载;;因因为为redis会会生生成成一一个个新新的的aof文文件件