文章目录
Redis RDB 和AOF 的
因为Redis是
内存数据库
,它将自己的数据库状态储存在内存
里面,所以如果不想办法将储存在内存中的数据库状态保存到磁盘
里面,那么一旦服务器进程退出,服务器中的数据库状态也会消失不见。为了解决这个问题,Redis提供了RDB
持久化功能和AOF
持久化 两种方式
RDB持久化
RDB持久化功能所生成的RDB文件
是一个经过压缩的二进制文
件,通过该文件可以还原生成RDB文件时的数据库
状态
但是Redis服务器如何保存和载入RDB文件的?
SAVE命令和BGSAVE命令的实现方式
save
SAVE命令会
阻塞
Redis服务器进程,直到RDB文件创建
完毕为止,在服务器进程阻塞期间,服务器不能处理任何命令请求
BGSAVE
- BGSAVE命令会派生出一个
子进程
,然后由子进程负责创建RDB文件
,服务器进程(父进程)继续处理命令请求:- BGSAVE命令执行期间,客户端发送的SAVE命令会被服务器拒绝。服务器禁止SAVE命令和BGSAVE命令同时执行是为了避免父进程(服务器进程)和子进程同时执行两个rdbSave调用,防止产生竞争条件。
- 在BGSAVE命令执行期间,客户端发送的BGSAVE命令会被服务器拒绝,因为同时执行两个BGSAVE命令也会产生竞争条件
底层代码
创建RDB文件的实际工作由
rdb.c/rdbSave
函数完成,SAVE命令和BGSAVE命令会以不同的方式调用这个函数
服务器文件载入状态
- RDB文件的载入工作是在服务器启动时自动执行的,所以Redis并没有专门用于载入RDB文件的命令,只要Redis服务器在启动时检测到RDB文件存在,它就会
自动载入RDB文件
,服务器在载入RDB文件期间,会一直处于阻塞状态,直到载入工作完成为止
redis.conf 配置BGsave
save 900 1
save 300 10
save 60 10000
只要满足以下三个条件中的任意一个,BGSAVE命令就会被执行:
- 服务器在900秒之内,对数据库进行了至少1次修改。
- 服务器在300秒之内,对数据库进行了至少10次修改。服务器在60秒之内,
- 对数据库进行了至少10000次修改
RDB文件结构
REDIS
RDB文件的最开头是REDIS部分,这个部分的长度为5字节,保存着“REDIS”五个字符。通过这五个字符,程序可以在载入文件时,快速检查所载入的文件是否RDB文件
db_version
长度为4字节,它的值是一个字符串表示的整数,这个整数记录了RDB文件的版本号
databases
databases部分包含着零个或任意多个数据库,以及各个数据库中的
键值对数据
EOF
EOF常量的长度为1字节,这个常量标志着RDB文件正文内容的结束,当读入程序遇到这个值的时候,它知道所有数据库的所有键值对都已经载入完毕了。
check_sum
是一个8字节长的无符号整数,保存着一个校验和,这个校验和是程序通过对REDIS、db_version、databases、EOF四个部分的内容进行计算得出的。
查看RDB文件
命令
od -c dump.rdb
root@674c34e6a73e:/data# od -c dump.rdb
AOF持久化
除了RDB持久化功能之外,Redis还提供了AOF(Append Only File)持久化功能。与
RDB持久
化通过保存数据库中的键值对
来记录数据库状态不同,AOF持久化
是通过保存Redis服务器所执行的写命令
来记录数据库状态的
持久化
RDB持久化保存数据库状态的方法是将
mess键值对
保存到RDB文件
中,而AOF持久化保存数据库状态的方法则是将服务器执行的SET
个命令保存到AOF文件
中。服务器在启动时,可以通过载入和执行AOF文件中保存的命令
来还原服务器关闭之前的数据库状态
优缺点
优点:
1、只有一个文件 dump.rdb,方便持久化。
2、容灾性好,一个文件可以保存到安全的磁盘。
3、性能最大化,(fork函数出) 子进程来完成写操作,让主进程继续处理命令,所以是 IO 最大化。使用单独子进程来进行持久化,主进程不会进行任何 IO 操作,保证了 redis 的高性能子进程备份的时候,父进程不会有任何的io操作(不会写入修改或删除),保证数据备份的完整性。
4.相对于数据集大时,比 AOF 的启动效率更高。
缺点:
1.发生故障的时候,有可能会丢失最后一次备份
2.子进程所占用的内存和父进程一摸一样(数据比较大),会造成CPU 负担。 如果服务器内存比较大的话可以忽略
3.不能做到实时备份。数据安全性低。RDB 是间隔一段时间进行持久化,如果持久化之间 redis 发生故障,会发生数据丢失。所以这种方式更适合数据要求不严谨的时候)
AOF持久化的实现(载入)
AOF持久化功能的实现可以分为
命令追加
(append)、文件写入
、文件同步(
sync)三个步骤。
命令追加
服务器在执行完一个写命令之后,会以协议格式将被执行的写命令追加到服务器状态的aof_buf缓冲区的末尾
AOF文件的写入与同步
Redis的服务器进程就是一个事件循环(loop)
,这个循环中的文件事件
负责接收客户端的命令请求,以及向客户端发送命令回复。
时间事件
则负责执行像serverCron函数这样需要定时运行的函数
文件事件
处理文件事件时可能会执行写命令,使得一些内容被追加到aof_buf缓冲区里面,所以在服务器每次结束一个事件循环之前,它都会调用
flushAppendOnlyFile函数
,考虑是否需要将aof_buf缓冲区中的内容写入和保存到AOF文件里面,flushAppendOnlyFile函数的行为由服务器配置的appendfsync选项的值来决定
appendfsync 三种选项(策略)
AOF文件的数据据还原
还原数据库
AOF 重写
原因
因为AOF持久化是通过保存被执行的写命令来记录数据库状态的,所以随着服务器运行时间的流逝,AOF文件中的内容会越来越多,文件的体积也会越来越大,如果不加以控制的话,体积过大的AOF文件很可能对Redis服务器、甚至整个宿主计算机造成影响,并且AOF文件的体积越大,使用AOF文件来进行数据还原所需的时间就越多。
AOF文件重写的实现
虽然Redis将生成
新AOF文件
替换旧AOF文件
的功能命名为“AOF文件重写
”,但实际上,AOF文件重写并不需要对现有的AOF文件进行任何读取、分析或者写入操作,这个功能是通过读取服务器当前的数据库
状态来实现的。
重写后的AOF文件为什么可以变小?有如下原因:
- 进程内已经超时的数据不再写文件。
- 旧的AOF文件含有无效命令,如del key1、set a 111、set a 222等。重写使用进程内数据直接生成,这样新的AOF文件只保留最终数据的写入命令。
- 多条写命令可以合并为一个,如lpush list a、lpush list b、 lpush list c 可以转化为:lpush list a b c。
AOF后台重写
子进程进行AOF重写期间,服务器进程(父进程)可以继续处理命令请求。
进程带有服务器进程的数据副本,使用子进程而不是线程,可以在避免使用锁的情况下,保证数据的安全性。
在子进程执行AOF重写期间,服务器进程需要执行以下三个工作:
- 执行客户端发来的命令。
- 将执行后的写命令追加到AOF缓冲区。
- 将执行后的写命令追加到AOF重写缓冲区。
优缺点
优点:
1、数据安全,aof 持久化可以配置 appendfsync 属性,有 always,每进行一次 命令操作就记录到 aof 文件中一次。
2、通过 append 模式写文件,即使中途服务器宕机,可以通过 redis-check-aof 工具解决数据一致性问题。
3、AOF 机制的 rewrite(重写) 模式。AOF 文件没被 rewrite 之前(文件过大时会对命令 进行合并重写),可以删除其中的某些命令(比如误操作的 flushall))
缺点:
1、AOF 文件比 RDB 文件大,且恢复速度慢。
2、数据集大的时候,比 rdb 启动效率低。