redis源码学习常态化版权声明
原创作为web作为发展部的一员,相信每个人在面试经历中都会遇到这样的问题:redis它是如何持续下去的?
不要急着给出答案,先停下来想一想,然后再看下面的介绍。我希望你读完这篇文章后能回答这个问题。
为什么需要坚持不懈?
由于Redis它是一种内存数据库,即服务器运行时,系统为其分配一部分内存存储数据。一旦服务器挂起或突然停机,数据库中的数据就会丢失。为了在服务器突然关闭的情况下保存数据,必须将数据从内存持久保存到磁盘。
对于持续存在的程序,将数据从程序写入计算机磁盘的过程如下:
1客户端向数据库发送写指令(此时数据在客户端的内存中)
2,数据库收到写入的指令和数据(此时数据在服务器的内存中)
3数据库发起系统调用,将数据写入磁盘(此时数据在内核的内存中)
4操作系统将数据传输到磁盘控制器(此时数据在磁盘高速缓存中)
5磁盘控制器执行实际将数据写入物理介质(例如磁盘)的操作
如果只考虑数据库级别,数据在第三阶段后将是安全的。此时,系统调用已经启动。即使数据库进程崩溃,系统调用也会继续,数据可以成功写入磁盘。
在此步骤之后,在第一个步骤中4步骤内核会将数据从内核缓存保存到磁盘缓存,但出于系统效率的考虑,此操作在默认情况下可能不会执行得太频繁30s一次,这意味着如果此步骤失败或服务器在执行时突然关闭,则可能会出现30s数据丢失了,这个更常见的灾难性问题也需要考虑。
POSIX API还提供了一个系统调用来强制内核将缓存数据写入磁盘,这是更常见的。fsync系统调用。
int fsync(int fd);
fsync该函数仅用于文件描述符。fd指定的文件工作,并等待写入磁盘操作结束后才返回。每次呼叫fsync则初始化写入操作,并将缓冲区数据写入磁盘。fsync()当写入操作完成时,该函数会阻止该进程。如果其他线程正在写入相同的文件,它还会阻止其他线程,直到写入操作完成。
持久化
持久性是一种在持久状态和瞬时状态之间转换程序数据的机制。对于程序来说,程序中的数据在内存中。如果不及时同步写入磁盘,一旦断电或程序突然崩溃,数据就会丢失。只有及时将数据同步到磁盘上,才能永久保存数据,不会造成停机镜像数据的有效性。持久性是将数据从程序同步到磁盘的过程。
转存失败 重新上传 取消
Redis的持久化
redis有RDB和AOF坚持下去有两种方法。RDB是快照文件、redis通过执行SAVE/BGSAVE命令执行数据备份时,将redis保存当前数据 *.rdb
在该文件中,该文件保存所有数据集。AOF是服务器通过读取配置,在指定的时间内追加。redis写下命令。 *.aof
文件,是一种增量的持久化方式。
RDB
RDB文件通过SAVE或BGSAVE命令执行。
SAVE命令将阻止Redis服务流程RDB直到创建了该文件。
BGSAVE命令通过fork子流程,还有子流程要创建。RDB文件、父进程和子进程共享数据段,父进程继续提供读写服务,子进程实现备份功能。BGSAVE仅当需要修改共享数据段时才复制该阶段,即。COW(Copy On Write)。SAVE创建RDB只要满足其中一个条件,就可以通过设置多个保存条件在后台执行文件。SAVE操作。
SAVE和BGSAVE该命令的实现代码如下:
void saveCommand(client *c) {
// BGSAVE它在执行时不能执行。SAVE
if (server.rdb_child_pid != -1) {
addReplyError(c,"Background save already in progress");
return;
}
rdbSaveInfo rsi, *rsiptr;
rsiptr = rdbPopulateSaveInfo(&rsi);
// 调用rdbSave功能执行备份(阻止当前客户端)
if (rdbSave(server.rdb_filename,rsiptr) == C_OK) {
addReply(c,shared.ok);
} else {
addReply(c,shared.err);
}
}
/*
* BGSAVE 命令实现 [可选参数"schedule"]
*/
void bgsaveCommand(client *c) {
int schedule = 0;
/* 当AOF在执行时,SCHEDULE参数修改BGSAVE的效果
* BGSAVE将在以后执行,而不是报告错误
* 可以理解为:BGSAVE在议程上
*/
if (c->argc > 1) {
// 参数只能是"schedule"
if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,"schedule")) {
schedule = 1;
} else {
addReply(c,shared.syntaxerr);
return;
}
}
// BGSAVE正在执行,不执行操作
if (server.rdb_child_pid != -1) {
addReplyError(c,"Background save already in progress");
} else if (server.aof_child_pid != -1) {
// aof正在执行,如果schedule==1,BGSAVE在议程上
if (schedule) {
server.rdb_bgsave_scheduled = 1;
addReplyStatus(c,"Background saving scheduled");
} else {
addReplyError(c,
"An AOF log rewriting in progress: cant BGSAVE right now. "
"Use BGSAVE SCHEDULE in order to schedule a BGSAVE whenever "
"possible.");
}
} else if (rdbSaveBackground(server.rdb_filename,NULL) == C_OK) {// 否则调用rdbSaveBackground执行备份操作
addReplyStatus(c,"Background saving started");
} else {
addReply(c,shared.err);
}
}
有了RDB文件完成后,如果关闭服务器或需要添加新的服务器,则可以在重启后加载数据库服务器。RDB该文件还原以前备份的数据。
但是bgsave耗时长,实时性不够强,关机时会造成大量数据丢失。
AOF(Append Only File)
RDB该文件保存数据库的密钥值对数据,AOF保存的是数据库执行的WRITE命令。
AOF实施过程分为三个步骤:
append->write->fsync
appendAPPEND命令AOF缓冲区,write将缓冲器的内容写入程序缓冲器,fsync将程序缓冲区的内容写入文件。
当AOF当持久性功能打开时,服务器会为执行的每个命令将命令附加到协议格式。redisServer结构体的aof_buf缓冲区,这里不描述具体的协议。
AOF持久期有一个配置选项:appendfsync。该选项有三个值:
always:所有内容均已写入并同步。aof文件
everysec:将aof_buf将缓冲区的内容写入AOF文件,如果距离上次同步的距离AOF文件的
no:将aof_buf缓冲区中的所有内容都是写入的。AOF文件,但不在AOF文件被同步,操作系统决定何时同步,这通常是默认设置。30s。
AOF持久化模式每个写入命令都被附加。AOF文件,当服务器继续运行时,AOF文件会变得越来越大,为了避免AOF生成的文件太大,服务器将是正确的。AOF文件将被重写,并且操作将是相同的。key合并相同的命令,从而减小文件的大小。
例如,要保存员工的姓名、性别和其他信息:
> hset employee_12345 name "hoohack"
> hset employee_12345 good_at "php"
> hset employee_12345 gender "male"
只需输入该散列键的状态,AOF该文件需要保存三个命令。如果有其他操作,如删除或更新值,则命令会更多,文件也会更大。通过重写,可以适当减小文件大小。
AOF重写的实现原理是先在服务器端数据库,然后遍历数据库,找出每个数据库中的所有键对象,得到键值对的键和值,再根据键的类型重写键值对。例如,上面的示例可以组合成以下命令:
> hset employee_12345 name "hoohack" good_at "php" gender "male"。
AOF重写执行大量的写操作,Redis它是单线程的,因此如果服务器直接调用重写,则服务器无法处理其他命令,因此Redis服务器有一个新的单一进程要执行。AOF重写。
Redis执行重写的过程:
在子进程中执行AOF重写时,服务器从客户端接收命令,执行来自客户端的命令,然后将执行的写命令附加到AOF缓冲区,并将执行的写命令追加到AOF重写缓冲区。
当子进程完成重写时,它将向服务器发送一个完整的信号,服务器将AOF将追加覆盖缓冲区中的所有内容AOF文件,然后自动重写现有的AOF文件。
RDB和AOF的优缺点
RDB持久化方法只有从服务器读取数据,才能将备份中的文件加载到程序中。AOF该方法必须创建一个要执行的伪客户端。
RDB文件小,保存了某个时间点之前的数据,适合灾备和主备同步。
RDB备份需要很长时间。如果数据量很大,在停机的情况下可能会丢失一些数据。此外,RDB只有在通过配置满足特定条件时才会执行此操作。如果在这段时间内发生停机,这部分数据也将丢失。
AOF这样,在相同数据集的情况下,文件大小将高于RDB这条路很大。
AOF持久化方法也因配置不同而有所不同。默认配置为每秒同步。最快的模式是同步每个命令。最糟糕的方法是等待系统执行fsync将缓冲区同步到磁盘文件,大多数操作系统都是30s。通常配置为每秒同步一次,因此最多会有1s数据丢失的风险。
哪种同步方式更好?
RDB和AOF多好的组合啊。启动定时任务,每小时备份服务器的当前数据状态,以日期和小时命名,并启动定时任务以删除无效的备份文件(例如,48几个小时前)。AOF配置为1s就一次。如此一来,损失最大的将是。1s数据,而如果。redis一旦发生雪崩,可以在不停止服务的情况下快速恢复到前一天的状态。
总结
Redis持久化方案不是一成不变的,需要将文中的理论与实际结果相结合来证明其可行性。
原创文章,写作有限,只有一点学问,如果文章有什么地方有误,希望能告知。
更多精彩内容,请关注个人公众号。
版权声明
所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除