一、Redis持久化原因:Redis是内存数据库,数据都是存放到内存中的,如突然宕机,数据就会丢失,因此必须有一种机制来保证redis在内存中的数据不会 丢失,这种机制就叫redis持久化机制。
二、支持的持久化有如下几种:
RDB(Redis 数据库):RDB 持久性以指定的时间间隔执行数据集的时间点快照(把某一时刻的状态到磁盘以文件的形式进行全量备份)。
AOF(仅追加文件):AOF 持久性记录服务器接收到的每个写操作。然后可以在服务器启动时再次重播这些操作,从而重建原始数据集。命令使用与 Redis 协议本身相同的格式进行记录。
RDB + AOF:还可在同一个实例中组合 AOF 和 RDB
三、RDB是Redis DataBase 的缩写,中文名为快照/内存快照,RDB持久化是把当前进程数据生成快照保存到磁盘上的过程,由于是某一时刻的快照,那么快照中的值要早于或者等于内存中的值。
1、默认情况下,Redis 将数据集的快照保存在磁盘上名为 dump.rdb 的二进制文件中。
2、Redis 提供了两个命令来生成 RDB 文件,分别是 save 和 bgsave。一般使用bgsave,既能提供数据的可靠性,也能避免影响redis性能。
①save:在主线程中执行,会导致阻塞;
②bgsave:创建一个子进程,专门用于写入 RDB 文件,避免了主线程的阻塞,这也是 Redis RDB 文件生成的默认配置。
伪代码
void SAVE(){ # 创建RDB文件
rdbSave();
}
void BGSAVE(){
# 创建子进程
pid = fork();
if (pid==0){
# 子进程创建RDB
rdbSave();
# 创建完成之后向父进程发送信息
signal_parent();
}else if (pid>0){
# 父进程(主线程)继续处理客户端请求,并通过轮询等待子进程的返回信号
handle_request_and_wait_signal();
}else{
# 处理异常
...
}
}
3、redis.conf中配置RDB:内存快照虽然可以通过命令来进行,但生产环境下多数情况都会设置其周期性执行条件,自动保存。
# 周期性执行条件的设置格式为
save <seconds> <changes>
# 默认的设置为:
save 900 1
save 300 10
save 60 10000
# 以下设置方式为关闭RDB快照功能
save ""
以上三项默认信息设置代表的意义是:
如果900秒内有1条Key信息发生变化,则进行快照;
如果300秒内有10条Key信息发生变化,则进行快照;
如果60秒内有10000条Key信息发生变化,则进行快照。
①savaparams属性
struct redisServer{
...
// 修改次数的计数器
long dirty;
// 上一次成功执行RDB快照的时间
time_t lastsave;
// 保存条件配置的数组
struct saveparam *saveparams;
...
}
struct saveparam{
// 秒数
time_t seconds;
// 修改次数
int changes;
}
②周期性检查保存条件:serverCron
函数默认每隔100毫秒就会执行一次,该函数的其中一个作用就是检查
save
命令设置的保存条件是否被满足,是则执行
BGSAVE
命令。伪代码
如下
void serverCron(){
...
for (saveparam in server.saveparams){
// 计算距离上次成功进行RDB快照多少时间
save_interval = unixtime_now() - server.lastsave;
// 如果距离上次快照时间超过条件设置时间 && 数据库修改次数超过条件所设置的次数,则执行快照操作
if (save_interval > saveparam.seconds && server.dirty >= saveparam.changes){
BGSAVE()
}
}
...
}
4、Copy-On-Write, COW
redis在执行bgsave生成快照的期间,将内存中的数据同步到硬盘的过程可能就会持续比较长的时间,而实际情况是这段时间Redis服务一般都会收到数据写操作请求。这时Redis 就会借助操作系统提供的写时复制技术(Copy-On-Write, COW),在执行快照的同时,正常处理写操作。
bgsave 子进程是由主线程 fork 生成的,可以共享主线程的所有内存数据。bgsave 子进程运行后,开始读取主线程的内存数据,并把它们写入 RDB 文件。
如果主线程对这些数据也都是读操作,那么,主线程和 bgsave 子进程相互不影响。但是,如果主线程要修改一块数据,那么,这块数据就会被复制一份,生成该数据的副本。然后,主线程在这个数据副本上进行修改。同时,bgsave 子进程可以继续把原来的数据写入 RDB 文件。
· 写时复制机制保证快照期间数据可修改,既保证了快照的完整性,也允许主线程同时对数据进行修改,避免了对正常业务的影响。
5、快照的频率:快照间隔越短,宕机时丢失数据越少。但频率越高,对磁盘会造成压力,另外也会频繁阻塞主线程。这个根据业务和实际来确定。
6、优点
①RDB文件是某个时间节点的快照,默认使用LZF算法进行压缩,压缩后的文件体积远远小于内存大小,适用于备份、全量复制等场景;
②Redis加载RDB文件恢复数据要远远快于AOF方式;
7、缺点:实时性不够,无法做到妙计持久化;
每次调用bgsave都需要fork子进程,占用系统资源;
RDB文件是二进制的,没有可读性