Redis 持久化设计
持久化的功能:Redis是内存数据库,数据都是存储在内存中的,为了避免进程退出导致数据的永久丢失,要定期将Redis中的数据以某种形式从内存保存到硬盘,当下次Reids重启时,利用持久化文件实现数据恢复。
RDB:将当前数据保存到硬盘
AOF:将每次执行的写命令保存到硬盘(类似MySQL的binlog)
1. RDB持久化RDB持久化是将当前进程中的数据生成快照保存到硬盘(因此也称作快照持久化),保存的文件后缀是rdb;当Redis重新启动时,可以读取快照文件恢复数据。
触发条件
手动触发 save 命令和bgsave命令都可以生成RDB文件, save命令会阻塞Redis服务进程,知道RDB文件创建完毕,bgsave命令则是创建一个子进程,由子进程来负责创建RDB文件,父进程继续处理请求,bgsave命令执行过程中,只有fork子进程时会阻塞服务器,而对于save命令,整个过程都会阻塞服务器,因此save已基本被废弃,线上环境要杜绝save的使用;后文中也将只介绍bgsave命令。此外,在自动触发RDB持久化时,Redis也会选择bgsave而不是save来进行持久化
SAVE 执行期间,AOF 写入可以在后台线程进行,BGREWRITEAOF 可以在子进程进行,所以这三种操作可以同时进行 ,为了避免性能问题,BGSAVE 和 BGREWRITEAOF 不能同时执行
自动触发
save m n
在配置文件中通过 save m n 命令,指定当前m秒内发生n次变化时,触发bgsave。
其中save 900 1的含义是:当时间到900秒时,如果redis数据发生了至少1次变化,则执行bgsave;save 300 10和save 60 10000同理。当三个save条件满足任意一个时,都会引起bgsave的调用.
Redis的save m n,是通过serverCron函数、dirty计数器、和lastsave时间戳来实现的-
serverCron函数,是Redis服务器的周期性操作函数,默认每隔100ms执行一次,该函数对服务器的状态进行维护,其中一项工作就是检测save m n 配置是否满足条件,如果满足就执行bgsave.
dirty计数器 记录服务器进行了多少起操作,修改,不是客户端执行了多少修改数据的命令
lastsave时间戳也是Reids服务器维持的一个状态,记录上一次成功执行bgsave的时间
save m n的原理如下:每隔100ms,执行serverCron函数;在serverCron函数中,遍历save m n配置的保存条件,只要有一个条件满足,就进行bgsave。对于每一个save m n条件,只有下面两条同时满足时才算满足:
当前时间-lastsave > m
dirty >= n
在主从复制场景下,如果从节点执行全量复制操作,则主节点会执行bgsave命令,并将rdb文件发送给从节点。
在执行shutdown命令时,自动执行rdb持久化
1.2 RDB文件 设置存储路径 - 配置文件:dir配置指定目录,dbfilename指定文件名。默认是Redis根目录下的dump.rdb文件 - 动态设置:config set dir {newdir} /// config set dbfilename {newFileName}
RDB文件 是经过压缩的二进制文件,默认采用LZF算法对RDB文件进行压缩,虽然压缩耗时,但是可以大大减小文件体积,默认是开启的,可以通过命令关闭:
config set rdbcompression no
RDB文件的压缩并不是针对整个文件进行的,而是对数据库中的字符串进行的,且只有在字符串达到一定长度(20字节)时才会进行
格式:
字段说明:
REDIS常量,保存‘REDIS'5个字符
db_version RDB文件的版本号
SELECTDB 表示一个完整的数据库(0号数据库),同理SELECTDB 3 pairs表示完整的3号数据库;只有当数据库中有键值对时,RDB文件中才会有该数据库的信息(上图所示的Redis中只有0号和3号数据库有键值对);如果Redis中所有的数据库都没有键值对,则这一部分直接省略。其中:SELECTDB是一个常量,代表后面跟着的是数据库号码;0和3是数据库号码;
KEY-VALUE-PAIRS: pairs则存储了具体的键值对信息,包括key、value值,及其数据类型、内部编码、过期时间、压缩信息等等
EOF 标志着数据库内容的结尾(不是文件的结尾),值为 rdb.h/EDIS_RDB_OPCODE_EOF (255)