Redis的热点数据是存放在缓存中,为了防止设备突然宕机,造成数据的丢失。持久化就是把内存中的热点数据存放到磁盘中去。下次启动时直接从磁盘中读取数据,这样就保证数据的持久化。
防止数据意外丢失,确保数据安全性。
redis提供了不同级别的持久化方式:
具体使用哪种持久化策略?
RDB持久化的触发为手动触发和自动触发两种。
在自动触发RDB持久时,Redis也会选择bgsave而不是save来进行持久化。
save m n
#自动触发最常见的情况是在配置文件中通过 savemn,指定当 m 秒内发生 n 次变化时,会触发 bgsave
vim /etc/redis/6379.conf
#219行,以下三个save条件满足任意一个时,都会引起bgsave的调用
save 900 1 :当时间到900秒时,如果redis数据发生了至少1次变化,则执行bgsave
save 300 10 :当时间到300秒时, 如果redis数据发生了至少10次变化,则执行bgsave
save 60 10000 :当时间到60秒时,如果redis数据发生了至少10000次变化, 则执行bgsave
#254行,指定 RDB 文件名
dbfilename dump.rdb
#264行,指定 RDB 文件和 AOF 文件所在目录
dir /var/lib/redis/6379
#242行,是否开启 RDB 文件压缩
rdbcompression yes
其他自动触发机制除了savemn以外,还有一些其他情况会触发bgsave:
AOF 持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。AOF 文件中的命令全部以 Redis 协议的格式来保存,新命令会被追加到文件的末尾。 Redis 还可以在后台对 AOF 文件进行重写(rewrite),使得 AOF 文件的体积不会超出保存数据集状态所需的实际大小。
AOF特点:
Redis服务器默认开启RDB,关闭AOF
要开启AOF,需要在配置文件中配置:
vim /etc/redis/6379.conf
#700行修改, 开启AOF
appendonly yes
#704行,指定AOF文件名称
appendfilename "appendonly.aof"
#796行,是否忽略最后一条可能存在问题的指令
aof-load-truncated yes
/etc/init.d/redis_6379 restart
#重启以使配置生效,开启 AOF

redis先将写命令追加到缓冲区,而不是直接写入文件,主要是为了避免每次有写命令都直接写入硬盘,导致硬盘IO成为redis负载的瓶颈。
命令追加的格式是redis命令请求的协议格式,它是一个纯文本格式,具有兼容性好、可读性强、容易处理、操作简单避免二次开销等优点。
在AOF文件中,除了用于指定数据库的select命令(如select0为选中0号数据库)是由redis添加的,其他都是客户端发送来的
策略涉及到操作系统的write函数和fsync函数,说明如下:
为了提高文件写入效率,在现代操作系统中,当用户调用write函数讲数据写入文件时,操作系统通常会讲数据缓存到一个内存缓冲区里,当缓冲区被填满后或超过指定时限后,才真正讲缓冲区的数据i写入到硬盘里。
这样的操作虽然提高了效率,但也带来了安全问题:如果计算机停机,内存缓冲区中的数据会丢失。
因此系统同时提供了fsync、fdatasync等同步函数,可以强制操作系统立刻将缓冲区中的数据写入到硬盘里,从而确保数据的安全性。
always:命令写入aof_buf后立即调用系统fsync操作同步到AOF文件,fsync完成后线程返回,always就是每次写命令都要同步到AOF文件,硬盘IO成为性能瓶颈,redis只能支持大约几百TPS写入,严重降低了redis的性能,即便是使用固态硬盘(SSD),每秒大约也只能处理几万个命令,而且会大大降低磁盘使用寿命。
no:命令写入ao_buf后调用系统write操作,不对AOF文件做fsync同步;同步操作系统负责,通常同步周期为30秒。这种情况下,文件同步的时间不可控,且缓冲区堆积的数据会很多,数据完全性无法保证。
eveysec:命令写入aof_buf后调用系统write操作,write完成后线程返回;fsync同步文件操作有专门的线程每秒调用一次。everysec是前面两个模式的折中模式,是性能和数据安全性的平衡,因此是redis的默认配置,也是最常用的模式。
文件重写是指定定期重写AOF文件,减少AOF文件的大小,但是需要注意的是,AOF重写是redis进程内的数据转换为命令,同步到新的AOF文件,而不会对旧iAOF文件进行任何读取、写入操作。
随着长时间的运行,redis服务器执行的写命令会越来越多,AOF文件也会越来越大,而过大的AOF文件不仅会影响服务器的正常运行,也会导致数据恢复的时间变长。可以通过文件重写降低AOF文件大小。
关于文件重写需要注意的是:对于AOF持久化来说,文件重写虽然是强烈推荐的,但并不是必须的,即使没有文件重写,数据也可以被持久化并在redis启动的时候导入,因此在一些现实中,会关闭自动的文件重写,然后通过定时任务来完成数据的更新。
过期的数据不再写入文件
无效的命令不再写入文件:如有数据被重复设置、有些数据被删除了等。
多条命令可以合并为一个:如sadd myset v1, sadd myset v2, sadd myset v3可以合并为 sadd myset v1 v2 v3
通过上述内容可以看出,由于重写后AOF执行的命令减少了,文件重写既可以减少文件占用的空间,也可以提高恢复速度。

(1):Redis 父进程首先判断当前是否存在正在执行 bgsave/bgrewriteaof 的子进程,如果存在则 bgrewriteaof 命令直接返回,如果存在 bgsave 命令则等 bgsave 执行完成后再执行
(2):父进程执行fork操作创建子进程,这个过程中父进程是阻塞的
(3.1):父进程 fork 后,bgrewriteaof 命令返回"Background append only file rewrite started"信息并不再阻塞父进程,并可以响应其他命令;Redis 的所有写命令依然写入 AOF 缓冲区,并根据 appendfsync 策略同步到硬盘,保证原有 AOF 机制的正确
(3.2):由于 fork 操作使用写时复制技术,子进程只能共享 fork 操作时的内存数据;由于父进程依然在响应命令,因此 Redis 使用 AOF 重写缓冲区(aof_ rewrite_buf)保存这部分数据,防止新 AOF 文件生成期间丢失这部分数据;也就是说,bgrewriteaof 执行期间,Redis 的写命令同时追加到 aof_ buf 和 aof_ rewirte_ buf 两个缓冲区
(4):子进程根据内存快照,按照命令合并规则写入到新的 AOF 文件
(5.1):子进程写完新的 AOF 文件后,向父进程发信号,父进程更新统计信息,具体可以通过 info persistence 查看
(5.2):父进程把 AOF 重写缓冲区的数据写入到新的 AOF 文件,这样就保证了新AOF文件所保存的数据库状态和服务器当前状态一致
(5.3):使用新的 AOF 文件替换老文件,完成 AOF 重写
分手动触发和自动触发
手动触发:
自动触发:
vim /etc/redis/ 6379. conf
#771行
auto-aof- rewrite-percentage 100
#当前 AOF 文件大小(即 aof_current_size)是上次日志重写时AOF文件大小(aof_base_size)两倍时,发生 BGREWRITEAOF操作
auto-aof -rewrite-min-size 64mb
#当前 AOF文件执行 BGREWRITEAOF 命令的最小值
#避免刚开始启动 Reids 时由于文件尺寸较小导致频繁的 BGREWRITEAOF

宕机等容易导致文件尾部不完整),且 aof-load- truncated 参数开启,则日志中会输出警告,Redis 忽略掉AOF文件的尾部,启动成功