RDB持久化
Redis是一个键值对数据库,服务器中通常包含着任意个非空数据库,而每个非数据库中又可以包含任意个键值对。我们将数据库中的非空数据库以及它们的键值对统称为数据库状态。
Redis提供了RDB持久化功能,这个功能可以将Redis在内存中的数据库状态保存到磁盘里面,避免数据意外丢失。
RDB持久化即可以手动执行,也可以根据服务器配置选项定期执行。该功能可以将某个时间点上的数据库状态保存到一个RDB文件中。RDB文件是一个经过压缩的二进制文件。
redis命令可以生成RDB文件,一个是SAVE,一个是BGSAVE。SAVE命令会阻塞Redis服务器进程,RDB文件创建完毕为止,在服务器进程阻塞期间,服务器不能处理任何命令请求。
BGSAVE命令会派生出一个子进程,然后由主进程负责创建RDB文件,服务器进程继续处理命令请求。
因为AOF文件的更新频率通常比RDB文件的更新频率高,如果服务器开启AOF持久化功能,那么服务器会优先使用AOF文件来还原数据库状态。只有在AOF持久化功能处于关闭状态时,服务器才会使用RDB文件来还原数据库状态。
在BGSAVE命令执行期间,客户端发送的SAVE、BGSAVE命令会被服务器拒绝,服务器禁止SAVE和BGSAVE命令同时执行时为了避免父进程和子进程同时执行两个rdbsave调用,产生竞争条件。BGREWRITEAOF和BGSAVE两个命令不能同时执行。
- 如果BGSAVE命令正在执行,那么客户端发送的BGREWRITEAOF命令会被延迟到BGSAVE命令会被延迟到BGSAVE命令执行完毕之后的执行。
- 如果BGREWRITEAOF命令正在执行,那么客户端发送的BGSAVE命令会被服务器拒绝。
服务器在载入RDB文件期间,会一直处于阻塞状态,直到载入工作完成为止。
- struct saveparam {
- time_t seconds; // 秒数
- int changes;//修改数
- };
复制代码除了saveparams数组之外,服务器状态还维持着一个dirty计数器,以及一个lastsave属性。
- dirty计数器记录距离上一次成功执行save命令或者bgsave命令之后,服务器对数据库状态进行了多少次修改。
- lastsave属性是unix时间戳,记录了服务器上一次成功执行save命令或者bgsave命令的时间。
Redis服务器周期性操作函数ServerCron默认每隔100毫秒就会执行,该函数用于对正在运行的服务器进行维护。满足条件会在这个函数中调用BGSAVE命令。
RDB文件结构
完整RDB文件所包含的各个部分:
- REDIS: 五个字符。
- db_version: 4字节,记录RDB文件的版本号。
- databases: 包含着零个或多个数据库,以及各个数据库中的键值对数据。
- EOF: 1字节,标志着RDB文件正文内容结束。
- check_sum: 8字节长的无符号整数,保存着一个校验和,通过前几个部分内容计算而来。以此检查RDB文件是否有出错或损坏的情况出现。
每个非空数据库的结构:
- selectDB: 切换数据库的标志。
- db_number: 数据库号码。
- key_value_pairs: 保存了数据库中所有键值对数据,如果键值对带有过期时间,那么过期时间也会和键值对保存在一起。
key_value_pairs结构
- 不带过期时间: TYPE key value
- 带过期时间: EXPIRETIME_MS ms TYPE key value
AOF持久化
AOF持久化是通过保存Redis服务器所执行的写命令来记录数据库状态的。服务器启动时,可以通过载入和执行AOF文件中保存的命令来还原服务器关闭之前的数据库状态。
AOF持久化功能的实现可以分为命令追加、文件写入、文件同步。
当AOF持久化处于打开状态,服务器在执行完一个写命令之后,会以协议格式将被执行的写命令将被追加的写命令追加到服务器状态的aof_buff缓冲区末尾。
redis服务器进程是一个事件循环,这个循环中的文件事件负责接受客户端的命令请求,以及向客户端发送命令回复,而时间事件则负责执行serverCron函数这样需要定时运行的函数。
appendfsync的参数配置以及含义:
- always: 将aof_buf缓冲区中的所有内容写入并同步到AOF文件。即使出现故障停机,aof持久化也只会丢失一个时间循环所产生的命令数据。
- everysec: 将aof_buf缓冲区中的所有内容写入到aof文件,如果上次同步aof文件的时间距离现在超过一秒,那么再次进行同步,并且这个同步操作是由一个线程专门负责执行的。即使出现故障停机也最多会丢失一秒钟的命令数据。
- no: 将aof_buf缓冲区的所有内容写入到aof文件,但并不对aof文件进行同步,何时同步由操作系统来操作。
现在操作系统,当用户调用write函数,将一些数据写入到文件的时候,操作系统通常会将数据暂时保存在一个内存缓冲区里面,等到缓冲区的空间被填满或者超过了指定时限之后,才真正将缓冲区的数据写入到磁盘,
服务器通过读入并执行aof文件里面保存的写命令,就可以还原服务器关闭之前的数据库状态。
AOF持久化是保存被执行的写命令来记录数据库状态的,所以随着服务器运行时间的流逝,AOF文件中内容会越来越多,使用aof继续进行数据还原的时间就越多。所以AOF提供了文件重写的功能。
AOF重写功能是通过读取服务器当前的数据库状态实现的。在保证进行重写aof一个命令不超过REDIS_AOF_REWRITE_ITEMS_PER_CMD的常量值,尽量使用一条命令进行重写。
AOF重写过程中,服务器还是会处理客户端命令请求,为了解决可能出现的数据不一致的问题,redis服务器设置了aof重写缓冲区,这个缓冲区在服务器创建子进程之后开始使用,当redis服务器执行完一个写命令。他会将这个写命令发送给aof缓冲区和aof重写缓冲区。
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |