redis持久化策略

仅供学习交流,如有错误请指出,如要转载请加上出处,谢谢

Redis提供了两种不同级别的持久化策略,RDB(redis database)持久化和AOF(append only file)持久化,它们应用在不同的场景中,各有千秋,以下是两种策略的实现方案

RDB(redis database)持久化

RDB(redis database)持久化是将内存中的数据生成一个特定格式的二进制的rdb文件,保存在磁盘中,在redis服务进程开启时通过读取磁盘中的rdb文件,数据又会还原到内存中。
rdb文件结构如下:

写入

指令写入

(1)SAVE:SAVE命令是在当前服务进程进行持久化操作,会阻塞其他的操作命令,直到RDB文件创建完毕
(2)BGSAVE:BGSAVE命令是创建一个子服务进程来专门处理持久化操作,其它操作命令在父服务进程继续执行

间隔性写入

在配置文件中设置写入触发条件,比如:SAVE 900 1,代表在900秒内对数据库进行一次修改,就触发写入程序。

载入

在服务器启动时,会对当前的持久化策略进行一个判断,如果当前已经开启了AOF持久化功能,那就会优先载入AOF还原程序,否则才载入RDB文件,整个载入过程都是阻塞的,保持数据的一致性。

AOF(append only file)持久化

AOF(append only file)持久化是基于redis服务器对键值对的操作命令生成的aof文件,保存在磁盘中,AOF文件的结构就是一串操作命令的文本文件

写入

AOF持久化通过以下步骤来进行持久化操作:

1. 命令追加(append)

在redis服务器中提供了一个sds(简单动态字符串)类型的缓冲区aof_buff,它用于记录redis的操作命令,也就是利用命令追加(append)模式将redis的操作命令一条一条的追加到该缓冲区的末尾

2. 写入AOF文件

将存储到缓冲区aof_buff中的指令通过调用flushAppendOnlyFile函数写入AOF文件中,写入AOF文件有三个策略:
● always:每一次数据操作,就将aof_buff缓冲区中的所有数据同步写入到AOF文件中
● everysec:启动一个线程,定时(每隔一秒)将aof_buff缓冲区中的所有数据同步写入AOF文件中
● no:不要求同步的情况下(aof_buff存储满溢),将aof_buff缓冲区中的数据写入AOF文件中
三个策略的安全性:always>everysec>no , 效率:no>everysec>always

载入

AOF持久化的载入方式是创建一个伪客户端去读取AOF文件,再在伪客户端中执行读取AOF文件中的一条条指令,直到完毕,数据库就恢复了之前的状态

重写

AOF文件就像是数据库操作的日志文件,记录了数据库各种操作的指令,但是会出现冗余的指令记录,长时间下去,会导致文件体积变得太大,比如,执行如下操作

1
2
3
4
RPUSH msg 'a'
RPUSH msg 'b'
RPUSH msg 'c'
RPUSH msg 'd'

如上所示,最后msg的结果是’a’,’b’,’c’,’d’,AOF文件就会有四条指令的记录,其实只要一条指令记录就可以了,这时,AOF持久化提供了一种重写的机制,它会创建一个子进程来处理,在子进程中创建一个新的AOF文件,针对上面情况,对一个对象的多次操作,它会用一条指令来表示,这样新的AOF文件就大大减少了存储体积,由于在子进程进行重写的时候,父进程还会处理操作指令,在重写期间执行的操作指令会被写到一个aof重写缓冲区中,所以不仅仅是aof缓冲区写入新的AOF文件中,aof重写缓冲区也会写进新的AOF文件中,这样和旧的AOF文件保存的数据库状态是一致的,最后替换旧的AOF文件

思考

优劣比较

RDB持久化的优点在于:
(1)RDB文件是一个非常紧凑的二进制文件,所以在远程传输上有很大的优势,可用于灾备中心的存储文件
(2)在载入数据库上,大数据量的情况下,RDB比AOF更加快速
(3)在持久化上,RDB持久化方式会fork一个子进程来执行,这样会保证Redis最大的性能
缺点如下:
(1)Redis的数据存储是基于内存的,如果碰上意外(宕机或者电源中断),如果你是每个五分钟甚至更长进行一次持久化,那么将会损失这几分钟的数据
(2)RDB是fork子进程来进行持久化的,所以当大数据集的时候,这会加大cpu的响应时间,影响Redis的处理速度
AOF持久化的优点在于:
(1)AOF使用的是fsync策略进行持久化,所以即使碰上意外,也只是损失1秒的数据
(2)AOF文件是一个日志文件,由指令集组成,通俗易懂,使使用者更加的好维护
缺点如下:
(1)相对于RDB文件来说,AOF文件相对过大了

如何选择使用哪种持久化方式

一般来说, 如果想达到足以媲美 PostgreSQL 的数据安全性, 你应该同时使用两种持久化功能。
如果你非常关心你的数据, 但仍然可以承受数分钟以内的数据丢失, 那么你可以只使用 RDB 持久化。
有很多用户都只使用 AOF 持久化, 但我们并不推荐这种方式: 因为定时生成 RDB 快照(snapshot)非常便于进行数据库备份, 并且 RDB 恢复数据集的速度也要比 AOF 恢复的速度要快, 除此之外, 使用 RDB 还可以避免之前提到的 AOF 程序的 bug

参考

http://www.redis.cn/topics/persistence.html
https://read.douban.com/ebook/7519526/(数据库的设计与实现)