Redis之持久化
Redis是基于内存的数据库,而内存是断电即失的,因此我们需要持久化功能。
而Redis的持久化有两种,一种是RDB,一种是AOF。RDB是基于数据的持久化,记录的是数据库中的数据。AOF是基于状态的持久化,记录的是修改数据库的操作。
需要注意的是如果服务器开启了AOF持久化,则会优先使用AOF持久化功能。
RDB
RDB文件的创建与载入
有两个命令可以生成RDB文件。save
和bgsave
。
- sava命令会阻塞Redis服务器进程,直到RDB文件创建完毕,在服务器进程被阻塞期间,服务器不能处理任何命令请求
- bgsave命令会派生出一个子进程负责创建RDB文件,服务器进程会继续处理命令请求
但是,及时使用bgsave派生出子进程创建RDB文件时,服务器进程也不能再次执行命令创建RDB文件,也就是说,同时只能存在一个进程创建RDB文件。
服务器在载入RDB文件期间(Redis服务器开启时会自动载入),会一直处于阻塞状态,直到载入工作完成
自动间隔性保存
用户可以通过save选项设置多个保存条件,只要任意一个条件被满足,服务器就会执行bgsave
命令
save 900 1
save 300 10
save 60 10000
那么只要满足以下三个条件之一,bgsave
命令就会被执行
- 服务器在900秒之内,对数据库进行了至少1次修改
- 服务器在300秒之内,对数据库进行了至少10次修改
- 服务器在60秒之内,对数据库进行了至少10000次修改
以上也是redis默认的save条件。
redis会在服务器中维护一个记录,记录了当前距离上一次save
或者bgsave
间隔多少时间和数据库进行了多少次修改。
redis服务器会周期性的检查(默认100毫秒)save条件是否满足,若满足则执行bgsave
命令。
AOF
AOF持久化功能的实现可以分为命令追加,文件写入,文件同步三个步骤
命令追加
当AOF持久化功能开启后,服务器在执行完一个修改命令后,会把改名了追加到aof_buf缓冲区的末尾
AOF文件写入和同步
写入:写入到内存缓冲区
同步: 同步到磁盘中
服务器配置的appendfsync
决定了AOF持久化的效率和安全性。他一共有三个值:always,everysec,no
-
当appendfsync的值为always时,服务器在每个事件循环都要将aof_buf缓冲区的内容写入AOF文件,并且同步AOF文件,所以always效率比较慢但是安全性比较高
-
当appendfsync的值为everysec时,服务器在每个事件循环都要将aof_buf缓冲区的内容写入AOF文件,但是每隔一秒会调用子线程对AOF文件进行同步,从效率上看 everysec比较快,并且就算出现故障宕机,也只丢失1秒的数据
-
当appendfsync的值为no时,服务器在每个事件循环都要将aof_buf缓冲区的内容写入AOF文件,何时同步AOF文件由操作系统决定,no时写入速度最快,但是出现故障宕机时会丢失上次同步到现在的数据
redis中appendfsync的值默认为everysec
AOF文件载入与数据还原
Redis读取AOF文件时会传建一个不带网络连接的伪客户端,伪客户端会执行AOF文件中的命令
AOF重写
因为AOF持久化是保存被执行的写命令来记录数据库状态的,所以随着时间的流逝,AOF文件中的内容会越来越大,AOF文件的体积也越来越大,为了解决这个问题,redis提供了AOF文件重写功能,通过该功能可以创建一个新的AOF文件来代替原来的AOF文件。
重写AOF文件是根据当前数据库的状态来实现的,举个例子
SADD animals "CAT"
SADD animals "DOG"
SADD animals "FISH"
SADD animals "PANDA"
SADD animals "TIGER"
这5条指令可以写为1条指令
SADD animas "CAT" "DOG" "FISH" "PANDA" "TIGER"
AOF重写功能是由后台进程来实现的,也就是说在进行AOF文件重写的过程中不会阻塞服务器进程。但是服务器进程新的命令会使得当前数据库状态和重写后的AOF文件不一致的情况。redis采用AOF重写缓冲区来解决这个问题。
若开始AOF重写后,服务器进程接到写命令会在AOF缓冲区和AOF重写缓冲区同时追加该命令,当重写AOF文件完成后,服务器会阻塞等待AOF重写缓冲区的命令写入到新的AOF文件中。