Redis 的持久化机制是什么?各自的优缺点?
Redis 提供两种持久化机制 RDB(默认) 和 AOF 机制:
RDB:是Redis DataBase缩写快照
RDB是Redis默认的持久化方式。按照一定的时间将内存的数据以快照的形式保存到硬盘中,对应产生的数据文件为dump.rdb。通过配置文件中的save参数来定义快照的周期。
-
优点:
-
适合大规模数据恢复
-
对数据完整性和一致性要求不高更适合使用
-
容灾性能好,一个文件可以保存在安全的磁盘。
-
性能最大化,fork子进程来完成写操作,让主进程继续处理命令,所以IO最大化。
-
相对于数据集大时,基于二进制存储的,比AOF的启动效率更高。
-
缺点:
-
数据安全性低。RDB 是间隔一段时间进行持久化,如果持久化之间 redis 发生故障,会发生数据丢失。所以这种方式更适合数据要求不严谨的时候)
-
Fork的时候,内存中的数据会被克隆一份,大致2倍的膨胀,需要考虑
-
在备份周期在一定间隔时间做一次备份,所以如果Redis意外down的话,就会丢失最后一次快照后所有修改
AOF:持久化
AOF 日志存储的是 Redis 服务器的顺序指令序列,AOF 日志只记录对内存进行修改的指令记录。
假设 AOF 日志记录了自 Redis 实例创建以来所有的修改性指令序列,那么就可以通过对一个空的 Redis 实例顺序执行所有的指令,也就是「重放」,来恢复 Redis 当前实例的内存数据结构的状态。
当二者同时打开,数据恢复Redis会优先选择AOF
(1)写入机制
Redis 在收到客户端修改命令后,先进行相应的校验,如果没问题,就立即将该命令存追加到 .aof 文件中,也就是先存到磁盘中,然后服务器再执行命令。这样就算遇到了突发的宕机情况情况,也只需将存储到 .aof 文件中的命令,进行一次“命令重演”就可以恢复到宕机前的状态。
(2)写入缓存
在上述执行过程中,有一个很重要的环节就是命令的写入,这是一个 IO 操作。Redis 为了提升写入效率,它不会将内容直接写入到磁盘中,而是将其放到一个内存缓存区(buffer)中,等到缓存区被填满时采用异步真正将缓存区中的内容写入到磁盘里。
这就意味着如果机器突然宕机,AOF 日志内容可能还没有来得及完全刷到磁盘中,这个时候就会出现日志丢失。那该怎么办?
Redis 为数据的安全性考虑,同样为 AOF 持久化提供了策略配置,打开 Redis 配置文件,如下图所示:
上述配置策略说明如下:
Always:服务器每写入一个命令,就调用一次 fsync函数,将缓冲区里面的命令写入到硬盘。这种模式下,服务器出现故障,也不会丢失任何已经成功执行的命令数据,但是其执行速度较慢; Everysec(默认):服务器每一秒调用一次 fsync 函数,将缓冲区里面的命令写入到硬盘。这种模式下,服务器出现故障,最多只丢失一秒钟内的执行的命令数据,通常都使用它作为 AOF 配置策略;
No:服务器不主动调用 fsync 函数,由操作系统决定何时将缓冲区里面的命令写入到硬盘。这种模式下,服务器遭遇意外停机时,丢失命令的数量是不确定的,所以这种策略,不确定性较大,不安全。
注意:Linux 系统的 fsync() 函数可以将指定文件的内容从内核缓存刷到硬盘中。 由于是 fsync 是磁盘 IO 操作,所以它很慢!如果 Redis 执行一条指令就要 fsync 一次(Always),那么 Redis 高性能将严重受到影响。 在生产环境的服务器中,Redis 通常是每隔 1s 左右执行一次 fsync 操作( Everysec),这样既保持了高性能,也让数据尽可能的少丢失。最后一种策略(No),让操作系统来决定何时将数据同步到磁盘,这种策略存在许多不确定性,所以不建议使用。
(3)重写机制
Redis 在长期运行的过程中,aof 文件会越变越长。如果机器宕机重启,“重演”整个 aof 文件会非常耗时,导致长时间 Redis 无法对外提供服务。因此就需要对 aof 文件做一下“瘦身”运动。
(4)自动触发AOF重写
Redis 为自动触发 AOF 重写功能,提供了相应的配置策略。如下所示:修改 Redis 配置文件,让服务器自动执行 BGREWRITEAOF
命令。
#默认配置项 auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb #表示触发AOF重写的最小文件体积,大于或等于64MB自动触发。
aof 文件的增量大于 100% 时才进行重写,也就是大一倍。比如,第一次重写时文件大小为 64M,那么第二次触发重写的体积为 128M,第三次重写为 256M,以此类推。如果将百分比值设置为 0 就表示关闭 AOF 自动重写功能。
(5)整个下来运行流程如下:
-
客户端的请求写命令会被append追加到AOF缓冲区内。
-
AOF缓冲区会根据AOF持久化策略[always,everysec,no]将操作sync同步到磁盘的AOF文件中。
-
AOF文件大小草果重写策略,或手动重写时,就会对AOF文件进行重写(rewrite),压缩AOF文件容量。
-
redis服务器重启时,会重新load加载AOF文件中的写操作达到数据恢复的目的
AOF配置
AOF默认不开启,可以在 redis.conf 文件中对AOF进行配置开启:
appendonly no # 是否开启AOF,yes:开启,no:不开启,默认为no appendfilename "appendonly.aof" # aof文件名称,默认为appendonly.aof dir ./ # aof文件所在目录,默认./,表示执行启动命令时所在的目录
AOF的优缺点:
-
优点:
-
数据安全,aof 持久化可以配置 appendfsync 属性,有 always,每进行一次 命令操作就记录到 aof 文件中一次。
-
通过 append 模式写文件,即使中途服务器宕机,可以通过 redis-check-aof 工具解决数据一致性问题。
-
AOF 机制的 rewrite 模式。AOF 文件没被 rewrite 之前(文件过大时会对命令 进行合并重写),可以删除其中的某些命令(比如误操作的 flushall))
-
缺点: 1、AOF 文件比 RDB 文件大,且恢复速度慢。 2、数据集大的时候,比 rdb 启动效率低。
2.Redis的过期策略
我们都知道,Redis是key-value数据库,我们可以设置Redis中缓存的key的过期时间。Redis的过期策略就是指当Redis中缓存的key过期了,Redis如何处理。
过期策略通常有三种:
定时删除
-
含义:在设置key的过期时间的同时,为该key创建一个定时器,让定时器在key的过期时间来临时,对key进行删除
-
优点:保证内存可以尽快释放
-
缺点:
-
若过期key很多,删除这些key会占用很多CPU的时间,在CPU时间紧张的情况下,CPU还要花费时间删除这些key.
-
(没人用)
-
惰性删除
-
含义:key过期的时候不删除,每次从数据库获取key的时候去检查是否过期,若过期,则删除,返回null。
-
优点:删除操作只发生在从数据库取出key的时候发生,而且只删除当前key,所以对CPU时间的占用是比较少的,而且此时的删除是已经到了非做不可的地步(如果此时还不删除的话,我们就会获取到了已经过期的key了)
-
缺点:若大量的key在超出事件后,很久一段时间内都没有被获取过,那么可能会发生内存泄漏。
定期删除
-
含义:每隔一段时间执行一次删除(在redis.conf配置文件设置hz,1s刷新的频率)过期key操作
-
优点:
-
通过限制删除操作的时长和频率,来减少删除操作对CPU时间占用--处理"定时删除"的缺点。
-
定期删除过期key 处理"惰性删除"的缺点。
-
RDB对过期key的处理
过期key对RDB没有任何影响
-
从内存数据库持久化数据到RDB文件
-
持久化key之前,会检查是否过期,过期的key不进入RDB文件
-
-
从RDB文件恢复数据到内存数据库
-
数据载入数据库之前,会对key先进行过期检查,如果过期,不导入数据库(主库情况)
-
AOF对过期key的处理
过期key对AOF没有任何影响
-
从内存数据库持久化数据到AOF文件:
-
当key过期后,还没有被删除,此时进行执行持久化操作(该key是不会进入aof文件的,因为没有发生修改命令)
-
当key过期后,在发生删除操作时,程序会向aof文件追加一条del命令(在将来的以aof文件恢复数据的时候该过期的键就会被删掉)
-
-
AOF重写
-
重写时,会先判断key是否过期,已过期的key不会重写到aof文件
-
Redis的过期时间和永久有效分别怎么设置
用expire 和 persist
3.Redis的内存淘汰策略
Redis的内存淘汰策略是指在Redis的用于缓存的内存不足时,怎么处理需要新写入且需要申请额外空间的数据。
全局的键空间选择性移除
-
noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。
-
allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。(这个是最常用的)
-
allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key。
设置过期时间的键空间选择性移除
-
volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。
-
volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key。
-
volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。
Redis的内存淘汰策略的选取并不会影响过期的key的处理。内存淘汰策略用于处理内存不足时的需要申请额外空间的数据;过期策略用于处理过期的缓存数据。