您的位置:首页 > 数据库 > Redis

辛星解读Redis中的RDB持久化方式

2015-02-20 11:13 399 查看
由于Redis通常是把数据保存到内存中的,但是当我们关机后再次启动Redis的时候,这些数据是不会保存的。为了解决这些问题,Redis提供了持久化机制,首先我们要看的就是它的RDB的持久化方式。在Redis运行时,RDB程序将内存中的数据库快照保存到磁盘文件中,在Redis重启的时候,RDB程序可以通过载入RDB文件来还原数据库的状态,重新把数据装入内存中。

Redis中的比较重要的两个函数就是rdbSave和rdbLoad,前者负责生成RDB文件,后者则是从RDB中读取文件载入到内存中。rdbSave函数负责将内存中的数据库数据以RDB格式保存到磁盘上,如果该RDB文件已经存在,那么新的RDB文件将会替换原有的文件。注意在保存RDB文件期间,主进程会被阻塞,知道保存完成。

其中我们的save命令会直接调用rdbSave,它会阻塞Redis主进程,直到保存完成为止。在主进程阻塞期间,服务器无法处理客户端的任何请求。所以当save正在执行时,新的save、bgsave、bgrewriteaof调用都会不起作用。只有在上一个save执行完毕且Redis重新开始接受请求之后,新的save、bgsave、bgrewrite命令才会被处理。注意aof是由后台线程完成的,而bgrewriteaof是由子进程完成的,所以在save的执行过程中,aof写入和bgrewriteaof可以同时执行。

而bgsave则是fork出一个子进程,由子进程来调用rdbSave,并且在保存完成之后向主进程发送信号,告诉主进程保存完毕。因为rbdSave是在子进程中被调用的,因此Redis服务器在bgsave执行期间仍然可以继续处理客户端的请求。

在执行save命令之前,服务器会检查bgsave是否正在执行中,如果是的话,服务器就不会调用rdbSave,而是直接向客户端返回一个出错信息,告诉客户端在bgsave期间,不能执行save。这样做可以避免save和bgsave调用的两个rdbSave交叉执行,从而造成竞争。如果bgsave正在执行,调用新的bgsave命令也会收到一条出错信息,它会告诉bgsave已经在执行当中。

注意bgrewriteaof和bgsave是不能同时执行的,如果bgsave正在执行,那么bgrewriteaof的重写请求会被延迟到bgsave执行完毕之后进行,执行bgrewriteaof命令的客户端会收到请求被延迟的回复。如果bgrewriteaof正在执行,那么调用bgsave的客户端将会收到出错信息,表示这两个命令不能同时执行。其实bgrewriteaof和bgsave这两个命令在操作方面没有什么冲突的地方,不能同时执行它们仅仅是出于性能方面的考虑,如果我们使用两个子进程,并且这两个子进程都在进行大量的磁盘写入操作,会对性能造成较大的拖累。

当Redis服务器启动时,rdbLoad函数就执行,它会读取RDB文件,并且将文件中的数据库载入到内存中。而且在载入期间,服务器每载入1000个键就会处理一次所有已到达的请求,不过它只能处理publish、subscribe、psubscribe、unsubscribe、punsubscribe这五个命令会被正确的处理,其他命令一概返回错误。等到载入完成之后,服务器才会正常的处理所有命令。这里主要是因为发布/订阅功能和其他数据库功能是完全隔离的,发布功能既不会读取数据也不会写入数据,因此在服务器载入期间,订阅与发布功能仍然是可以正常使用的,我们不必担心它会对数据的完整性产生任何影响。

不过值得注意的是因为aof文件的保存频率通常要高于RDB文件的保存频率,因此一般来说,aof文件的数据会比RDB文件的数据要新一些。如果服务器在启动时,打开了aof功能,那么程序优先使用AOF文件来还原数据,只有AOF功能没打开的时候,Redis才会使用RDB文件来还原数据。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: