《Redis设计与实现》学习笔记-持久化机制

同memcached(对不起,又躺枪了)等完全基于内存的缓存相比,Redis是提供了持久化功能的,这也是为什么在某些条件下Redis可以用来做存储而不仅仅是缓存,节点down机之后可以通过持久化的数据还原某个时间点的状态。Redis提供了两种持久化机制RDB和AOF,准确的讲应该是三种,Redis提供了虚拟内存机制,但是据说性能非常不靠谱,嗯,是据说,我并没有深入研究过。

RDB持久化

RDB持久化是把当前数据库数据备份到一个RDB文件中,RDB文件是一个经过压缩的二进制文件,通过这个文件可以还原生成RDB文件时的数据库状态。

Redis提供了两个命令用于生成RDB文件,即SAVE和BGSAVE。SAVE命令会阻塞服务器进程,而BGSAVE会生成一个子进程来创建RDB文件,不会阻塞服务器进程。

SAVE命令会阻塞主进程,在执行该命令的过程中服务器会拒绝客户端命令。只有当SAVE命令执行完之后服务器才会继续处理客户端的命令,而BGSAVE命令是在子进程中执行,在执行该命令的过程中服务器还可以继续处理客户端的命令。SAVE命令和BGSAVE命令不能同时执行,当正在执行BGSAVE命令时,客户端发送的SAVE命令会被拒绝,两个BGSAVE命令也不能同时执行。

Redis通过在配置文件添加save参数来自动保存RDB文件策略。比如在配置文件中添加下面三行配置:

save 900 1
save 300 10
save 60 10000
那么满足下列条件的任意一个时,服务器就是执行BGSAVE命令:

  • 服务器在900秒之内对数据库进行了至少一次修改。
  • 服务器在300秒之内对数据库进行了至少10次修改。
  • 服务器在60秒之内对数据库进行了至少10000次修改。

Redis通过一个saveparam结构体来保存save参数:

struct{
    time_t seconds;
    int changes;
}
服务器结构体redisServer添加了三个字段:

saveparams字段,保存所有的save参数,

dirty字段,来保存上一次成功执行SAVE或BGSAVE命令之后,服务器对数据库执行的修改次数。

lastsave字段,记录服务器上一次执行SAVE和BGSAVE的UNIX时间戳

struct{
    ...
    struct saveparam *saveparams;
    long long dirty;
    time_t lastsave;
    ...
};

AOF持久化

RDB是通过备份某个时间点的数据来保存数据库状态,而AOF是通过保存服务器所执行的命令来保存数据库的状态的。当结点down机重启时通过载入AOF文件并且执行文件中的命令就可以恢复生成AOF文件时的数据库状态,如果同时存在RDB文件和AOF文件,服务器优先载入AOF文件来还原数据库状态
AOF实现分为三步:命令追加、文件写入、文件同步。现代操作系统中为了提高文件写入效率,当用户调用了write函数时操作系统通常会将写入的数据暂时保存在一个内存缓冲区里面,等到缓冲区写满或者超过指定的时限之后,才真正地将缓冲区中的数据写入到磁盘中。
通过设置appendfsync参数来设置AOF文件生成策略,它有三个可选值:

  • always,将AOF缓冲区的所有内容写入并同步到AOF文件中,这种方式数据安全性最高,但是CPU消耗大。
  • everysec,将AOF缓冲区中的所有内容写入到AOF文件,如果上次同步AOF文件的时候距离现在超过一秒钟,那么再次对AOF文件进行同步,并且这个同步操作由一个线程专门负责执行,数据安全性不如always,当服务器出现故障时会出现1s的数据空窗期,但是CPU消耗较always小。
  • no,将AOF缓冲区中的所有内容写入到AOF文件,但并不对AOF文件进行同步,何时同步由操作系统来决定。这种方式CPU消耗低,但是数据安全性差,而且单次同步时间最长。
如果用户不进行设置,默认值时everysec。相比于RDB持久,AOF持久化执行的频率要高得多,所以AOF丢失数据的时间窗比RDB要小,但是也要耗费更多的CPU时间和IO资源。RDB和AOF还有一个不同点就是,RDB文件替换是一个原子操作所以RDB文件肯定是完整,而AOF文件有可能是不完整的,有可能命令没写完就down机了或者磁盘坏了。但是也不用担心这种情况,一是这种情况出现的概率非常低,二是Redis提供了修复AOF文件的工具。

当Redis服务器长时间运行时,AOF文件的内容会越来越多,文件的体积也会越来越大,为了解决这个问题,Redis提供了AOF文件重写功能,消除一些冗余命令,比如服务器执行过下面两条命令:

RPUSH list "A" "B"

LPOP list

那么重写之后会变成RPUSH list "A" 这一条命令。

Redis提供了 BGREWRITEAOF命令来执行AOF重写,AOF重写不对旧AOF文件有依赖,而是通过查询现有数据库中的键值对的状态来生成一个新的AOF文件,重写动作在子进程中完成,生成一个新文件然后重命名替换掉老文件。在重写的过程中,客户端请求的新命令会追加到AOF重写缓冲区中,子进程完成重写之后,发送一个信号消息通知主进程把重写缓冲区中的内容同步到重写后的AOF文件中,这个过程会阻塞主进程。
BGSAVE和BGREWRITEAOF命令不能同时执行:

  • 如果BGSAVE命令正在执行,那么BGREWRITEAOF命令会被延迟到BGSAVE完成之后执行
  • 如果BGREWRITEAOF命令正在执行,那么客户端发送的BGAVE命令会被拒绝



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值