RDB:Redis DataBase
将某一个时刻的内存快照(Snapshot)以二进制的方式写入磁盘。
触发方式分为手动触发和自动触发。
手动触发
- SAVE命令,会使Redis处于阻塞状态,直到RDB持久化完成,才会响应其他客户端发来的命令,所以在生成环境要慎用。
- BGSAVE命令,fork出一个子进程执行持久化,主进程只在fork过程中有短暂阻塞,子进程创建后主进程就可以响应客户端了。
这时,您可能会产生疑问:BGSAVE子进程在做持久化的时候,主进程在处理客户端读写请求,数据时时刻刻在变,这样生成出来的备份不就是乱的吗,极有可能产生一些脏数据啊?子进程其实利用了操作系统的一种机制写时拷贝策略(Copy-On-Write,简称COW),保证父进程和子进程在写时拷贝期间用的不是同快内存。如下图,当fork出子进程后,若父进程有写操作,则会拷贝出一个副本,在副本中修改这个数据;子进程读到的还是原来的数据,当子进程完成任务再将副本写回原数据中。
自动触发
- 配置文件save m n:在m秒内,如果有n个键值发生改变,则自动触发持久化,通过BGSAVE执行。若设置了多个,只要满足其一就会触发。(配置文件有默认配置,可注释掉)
- FLUSHALL命令:用于清空Redis中所有的数据库,会清空RDB文件,并重新生成新的空dump.rdb文件
- 主从同步:全量同步时会自动触发BGSAVE命令,生成rdb发送给从节点
- SHUTDOWN命令关闭Redis服务器时,也会自动触发RDB持久化(注意kill -9等意外关闭不会触发)
优点
- 整个Redis数据库将只包含一个dump.rdb,方便持久化。(子进程进行持久化时是新建一个临时rdb文件,当持久化完成就替换原先的dump.rdb文件)
- 是某个时刻的全量二进制备份,容灾性好,方便备份。
- 性能最大化,fork子进程来完成写操作,让主进程继续处理命令,所以是IO最大化。使用单独子进程来进行持久化,主进程不会进行任何IO操作,保证了Redis的高性能。
- 相对于数据集大时,比AOF的启动效率更高。
缺点
- 数据安全性低。RDB的自动触发是间隔一段时间满足条件才进行持久化,如果两次持久化之间的时候Redis发生故障,就会发生数据丢失。(所以这种方式更适合数据要求不严谨的时候)
- 由于RDB是通过fork子进程来协助完成数据持久化工作的,在fork完成前主进程会处于阻塞的状态,直到fork出子进程才恢复对客户端的服务。若为减少数据丢失的可能性而加大RDB的频率,会造成服务经常被阻塞,而且fork子进程会占用CPU。
AOF:Append Only File
以日志的形式记录服务器所处理的每一个写/删操作,查询操作不会被记录。以文本的方式进行记录,可以打开文件查看详细的操作记录。流程如下:
- 所有的写命令会追加到AOF缓冲中。
- AOF缓冲区根据对应的策略向硬盘进行同步操作。
- 随着AOF文件越来越大,需要定期对AOF文件进行重写(BGREWRITEAOF:相同的命令整合等),达到压缩的目的。
- 当Redis重启时,逐条运行AOF中的记录,进行数据恢复。
同步策略
- 每秒同步:异步完成,效率非常高,一旦系统出现宕机,那么这一秒内所作的修改将会丢失。
- 每修改同步:同步持久化,每次发生数据变化都会立刻记录到磁盘中(fsync将缓冲区刷盘到磁盘中),最多丢失一条操作。
- 不同步:由操作系统控制,可能丢失较多数据。
优点
- 数据较为安全,丢失更少。
- 通过append模式写文件,即使中途服务器宕机也不会破坏已存在的内容,可通过redis-check-aof工具解决数据一致性问题。
- AOF机制的定期rewrite可以达到压缩的目的。
缺点
- AOF文件比RDB文件更大,且恢复速度更慢。
- 数据集大的时候,启动效率较低,因为要逐条执行AOF中的操作,恢复内存中的数据。
- AOF运行效率没有RDB高
当AOF和RDB都开启时,因为AOF比RDB更新频率更高,数据更能有保证,Redis优先使用AOF还原数据。