Redis的数据是基于内存存储的,为了防止Redis在重启或宕机等情况下数据丢失,Redis提供了两种持久化方式:RDB机制、AOF机制。
将内存中的数据以快照的方式保存到磁盘文件中(把全量数据以二进制压缩文件的方式存储到磁盘文件)。
触发快照的命令:
触发快照的时机:
以近乎实时的方式把执行的每条数据变动命令进行追加存储到AOF的缓存区里面, 然后再把缓存的数据写入到磁盘的AOF文件里面。
AOF默认是关闭的,通过redis.conf配置文件进行开启。
AOF日志是持续增量的备份,是基于写命令存储的可读的文本文件。AOF日志会在持续运行中持续增大,由于Redis重启过程需要优先加载AOF日志进行指令重放以恢复数据,恢复时间会无比漫长。所以需要定期进行AOF重写,对AOF日志进行瘦身。
目前AOF是Redis持久化的主流方式。
优点:
缺点:
优点:
缺点:
建议AOF、RDB一起用。单独用RDB可能会丢失很多数据,单独用AOF数据恢复没RDB来的快,出问题的时候第一时间用RDB恢复,然后AOF做数据补全,冷备热备一起用。
对于设置了过期时间的数据,当数据过期之后,Redis就需要将这些数据进行清除,释放占用的内存空间。
定时删除
在设置某个 key 的过期时间同时,我们创建一个定时器,让定时器在该过期时间到来时,立即执行对其进行删除的操作。
定期删除
每隔一段时间,我们就对一些key进行检查,删除里面过期的key。
优点:可以通过限制删除操作执行的时长和频率来减少删除操作对 CPU 的影响。另外定期删除,也能有效释放过期键占用的内存。
缺点:难以确定删除操作执行的时长和频率。
如果执行的太频繁,定期删除策略变得和定时删除策略一样,对CPU不友好
如果执行的太少,那又和惰性删除一样了,过期键占用的内存不会及时得到释放。在获取某个键时,如果某个键的过期时间已经到了,但是还没执行定期删除,那么就会返回这个键的值,这是一定务不能忍受的。
惰性删除
设置该 key 过期时间后,我们不去管它,当需要该 key 时,我们在检查其是否过期,如果过期,我们就删掉它。
Redis中主要使用定期删除+惰性删除两种数据过期清除策略。
Redis默认每隔100ms就随机抽取一些设置了过期时间的key,检查其是否过期,如果有过期就删除。注意这里是随机抽取的。
过期键的定期删除策略由activeExpireCycle函数实现,每当Redis服务器的周期性操作serverCron函数执行时,activeExpireCycle函数就会被调用,它在规定的时间内,分多次遍历服务器中的各个数据库,从数据库的expires字典中随机检查一部分键的过期时间,并删除其中的过期键。
为什么要随机抽取?
假如Redis存了大量的key ,每隔100ms就遍历所有的设置过期时间的key的,会给CPU带来很大的负载。
为什么不用定时删除策略?
定时删除,用一个定时器来负责监视key,过期则自动删除。虽然内存及时释放,但是十分消耗CPU资源。
定期删除可能导致很多过期的key到了时间并没有被删除掉,这时就要使用到惰性删除。
在获取某个key的时候,redis会检查这个key如果是否设置了过期时间并且过期了,如果是的话就删除。
生成RDB文件时:
在执行save命令或者bgsave命令创建一个新的RDB文件时,程序会对数据库中的键进行检查,已过期的键不会被保存到新创建的RDB文件中。
加载RDB文件时:
在启动Redis服务器时,如果服务器只开启了RDB持久化,那么服务器将会载入RDB文件:
如果服务器以主服务器模式运行,在载入RDB文件时,程序会对文件中保存的键进行检查,未过期的键会被载入到数据库中,过期键会被忽略。
如果服务器以从服务器模式运行,在载入RDB文件时,文件中保存的所有键,不论是否过期,都会被载入到数据库中。
因为主从服务器在进行数据同步(完整重同步)的时候,从服务器的数据库会被清空,所以一般情况下,过期键对载入RDB文件的从服务器不会造成影响。
AOF文件写入
如果数据库中的某个键已经过期,并且服务器开启了AOF持久化功能,当过期键被定期删除或者惰性删除后,程序会向AOF文件追加一条DEL命令,显式记录该键已被删除。
以惰性删除为例:
AOF文件重写
在执行AOF文件重写时,程序会对数据库中的键进行检查,已过期的键不会被保存到重写后的AOF文件中。
如果某个key过期后,定期删除没删除成功,然后也没再次去请求key,也就是说惰性删除也没生效。
这时,如果大量过期的key堆积在内存中,redis的内存会越来越高,导致redis的内存块耗尽。那么就应该采用内存淘汰机制。
当Redis内存不足时,会通过内存淘汰策略删除部分键值对。
Redis内存设置
配置文件redis.conf中,通过参数 maxmemory