Redis持久化之RDB与AOF

Redis是一个内存数据库,他将自己的数据库状态储存在内存中,所以,如果不想办法将内存中的数据库状态保存到磁盘里面,一旦redis服务器进程退出,服务器中的数据库状态就会消失,为了解决这样的问题,Redis提供了持久化功能(RDB持久化、AOF持久化),将数据库状态保存保存在磁盘中,避免了数据的意外丢失。

RDB持久化

RDB持久化既可以手动执行,也可以根据服务器配置定期执行,将数据库状态保存到一个RDB文件中,服务器可以根据载入的RDB文件,恢复到生成RDB文件时,数据库的状态。redis有两个命令生成RDB文件,SAVE和BGSAVE:

  1. SAVE命令,在执行期间,会阻塞Redis服务器进程,直到RDB文件创建完毕为止,在服务器进程阻塞期间,服务器不能处理任何命令请求。
  2. BGSAVE命令,会派生出一个子进程,然后由子进程负责创建RDB文件,服务器进程(父进程)继续处理命令请求。

服务器在启动的时候,根据具体情况选择加载RDB文件恢复数据库状态,在此期间,服务器进程会一直处于阻塞状态,直到载入工作完成为止。

自动间隔性保存

BGSAVE指令可以在不阻塞服务器进程的情况下执行,redis可以通过设置服务器端的save选项让服务器每隔一段时间执行一次BGSAVE命令。命令如下:

  1. save 600 1(服务器在600秒内,对数据库执行了至少1次修改)
  2. save 900 10(服务器在900秒内,对数据库执行了至少10次修改)

可以设置多个条件,,只要满足任意一个条件,服务器就会执行BGSAVE命令。如果没有主动设置保存条件,服务器会设置默认的条件:

  1. save 900 1;
  2. save 300 10;
  3. save 60 10000;

服务器根据save选项设置的保存条件,设置服务器状态,redisService的结构如下:

struct redisServer {
	//...
	//记录了保存条件的数组
	struct saveparam *saveparams;
	//修改计数器
	long long dirty;
	//上一次保存的时间
	time_t lastsave;
	//...
};

saveparams是一个数组结构,结构如下:

struct saveparam {
	//秒数
	time_t seconds;
	//修改数
	int changes;
};

dirty计数器记录距离上一次成功执行SAVE命令或者BGSAVE命令之后,服务器对数据库进行了多少次修改(包含写入、删除、更新等操作)
lastsave属性是一个UNIX时间戳,记录了服务器上一次成功执行SAVE和BGSAVE命令的时间。
Redis的服务器周期性操作函数serverCron默认每隔100毫秒就会执行一次,该函数用于对正在运行的服务器进行维护,它的其中一项工作就是检查save选项所设置的保存条件是否已经满足,如果满足的话,就执行BGSAVE命令。
以下伪代码展示了serverCron函数检查保存条件的过程:

def serverCron():
    # ...
    #遍历所有保存条件
for saveparam in server.saveparams:
        #计算距离上次执行保存操作有多少秒
        save_interval = unixtime_now()-server.lastsave
        #如果数据库状态的修改次数超过条件所设置的次数
        #并且距离上次保存的时间超过条件所设置的时间
        #那么执行保存操作
        if server.dirty >= saveparam.changes and \
           save_interval > saveparam.seconds:
            BGSAVE()
    # ...

当BGSAVE执行之后,会重置redisServer中的dirty为0,lastsave为当前时间。

RDB文件格式

在这里插入图片描述

  1. REDIS:常量,保存着”REDIS”5个字符。
  2. db_version:RDB文件的版本号。
  3. SELECTDB 0 pairs:表示一个完整的数据库(0号数据库),同理SELECTDB 3 pairs表示完整的3号数据库;只有当数据库中有键值对时,RDB文件中才会有该数据库的信息(上图所示的Redis中只有0号和3号数据库有键值对);如果Redis中所有的数据库都没有键值对,则这一部分直接省略。其中:SELECTDB是一个常量,代表后面跟着的是数据库号码;0和3是数据库号码;pairs则存储了具体的键值对信息,包括key、value值,及其数据类型、内部编码、过期时间、压缩信息等等。
  4. EOF:常量,标志RDB文件正文内容结束。
  5. check_sum:前面所有内容的校验和;Redis在载入RBD文件时,会计算前面的校验和并与check_sum值比较,判断文件是否损坏。

AOF持久化

与RDB持久化通过保存数据库中的键值对来记录数据库状态不同,AOF持久化是通过保存redis服务器所执行的写命令来记录数据库状态。AOF持久化功能的实现可以分为命令追加、文件写入、文件同步三个步骤。
命令追加
当AOF持久化功能打开时,服务器在执行完一个写命令后,将被执行的写命令追加到服务器状态的aof_buf缓冲区的末尾。Redis先将写命令追加到缓冲区,而不是直接写入文件,主要是为了避免每次有写命令都直接写入硬盘,导致硬盘IO成为Redis负载的瓶颈。
AOF文件的写入和同步
根据不同的同步策略(设置的appendfsync的值),将aof_buf中的内容同步到磁盘中。appendfsync各值的含义:

  1. always,服务器每个事件循环都会将aof_buf缓冲区中的内容写入到AOF文件,并且同步AOF文件,所以always的效率是最低,但安全性是最高的,即使出现机器故障等问题,丢失的数据量越是最少的。
  2. no,服务器每个事件循环,都会将aof_buf缓冲区的内容写到AOF文件中,至于何时对AOF文件进行同步,则由操作系统控制。
  3. everysec,服务器每个事件循环,都会将aof_buf缓冲区的内容写到AOF文件中,并且每隔1秒钟,对AOF文件同步一次,效率与设置为no是相近,数据安全性较高,机器出现故障,只会丢失一秒钟的数据。
    AOF文件载入
    AOF文件中存储的是重建数据库所需的所有的写命令,所以服务器启动后,只需要将文件循环执行AOF里的写命令,就可以恢复数据库的状态。
    AOF文件重写
    AOF文件里存储的是所有的写命令,随着时间的推移,AOF文件会越来越大,为了解决这样的问题,redis提供了AOF文件重写功能。AOF文件重写,不会对于现有的AOF文件进行任何的读取、分析和写入操作,而是新建一个文件,通过读取服务器当前数据库状态,存储写入命令,新旧两个AOF文件,索堡村的数据库状态是完全相同的,但是,新的AOF文件中不会包含任何浪费空间的冗余数据,所以新的AOF文件的大小会小很多。

RDB与AOF的选择

RDB持久化唯一,也是最大的缺点就是其数据快照的持久化方式,必然做不到实时的持久化,在很多业务场景中,数据丢失是不能接受的,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值