Redis是内存数据库,存在断电重连后数据消失的问题。为解决这一问题,Redis提供了将数据持久化到硬盘的功能,包括RDB和AOF两种方式,两种方式各有其优缺点。 RDB方式: 在默认情况下,Redis将数据库快照保存在名字为dump.rdb的二进制文件中,并在启动时自动加载rdb文件,恢复之前保存的数据。
RDB机制将数据写入磁盘两种方式: 1、save 这是一种阻塞方式,主线程在执行save时会暂停客户端请求,直到数据保存完毕。 执行方法为通过客户端中手动输入save命令执行。 2、bgsave 这是非阻塞的方式,Redis服务可以正常接收客户端请求。Redis会fork()一个子进程来创建rdb文件,子进程处理完毕后会向父进程发送一个信号,通知它处理完毕。父进程用新的dump.rdb来替代旧文件。 执行方法为满足配置文件中的条件时,自动执行。
配置文件中对应部分内容为: save [seconds] [changes] 意为在[seconds]秒内如果发生了[changes]次数据修改,则进行一次RDB快照保存,例如 save 60 100 会让Redis每60秒检查一次数据变更情况,如果发生了100次或以上的数据变更,则进行RDB快照保存。可以配置多条save指令,让Redis执行多级的快照保存策略。Redis默认开启RDB快照。
RDB方式优点: 1、完全备份,不同时间的数据集备份可以做到多版本恢复。 2、对性能影响最小,如上文所述,Redis在保存RDB快照时会fork()出子进程来进行,几乎不影响Redis处理客户端请求的效率。 3、RDB文件为二进制文件,方便网络传输,适合灾难恢复。 4、恢复大数据集速度较AOF快。
RDB方式缺点: 1、可能会丢失最近写入,修改而未能持久化的数据。 2、如果数据集较大且CPU不够强,在fork()子进程时会非常耗时,会造成毫秒级不能相应客户端请求。
AOF方式 采用AOF持久方式时,Redis会把所有写操作记录在一个AOF日志文件里。在Redis重启时,会把AOF文件中记录的所有写操作顺序执行一遍,确保数据恢复到最新。 AOF默认是关闭的,若要开启,把配置文件中的appendonly修改为yes即可。
AOF机制下将数据写入磁盘有三种写入策略,分别为always/everysec/no: 1、appendfsync always:服务器每写入一个命令,就调用一次fdatasync,将数据写入硬盘。在这种模式下,服务器出现故障,也不会丢失任何已经成功执行的数据命令。但是,因为每有一个操作就要同步一次,所以速度最慢。 2、appendfsync everysec(默认):服务器每秒调用一次fdatasync,将数据写入硬盘。这种模式下,服务器出现故障,最多丢失一秒内所执行的命令数据。速度较快。 3、appendfsync no:服务器不主动调用fdatasync,由操作系统决定何时将数据写入硬盘。这种情况下,服务器遭到意外停机时,丢失命令的数量是不确定的。速度较快。
AOF日志重写: 随着AOF不断的记录写操作日志,因为AOF所有的操作都会被记录,所以一定会有些无用的日志。比如对一个key修改后又把这个key删了,那么对key修改的这个操作就是无用的日志操作。大量无用的日志会让AOF文件过大,也会让数据恢复的时间过长。不过AOF提供了rewrite功能,可以重写AOF日志,只保留能把数据恢复到最新状态的最小写操作集。 1、执行AOF重写请求 2、父进程执行fork()创建子进程,开销等同于RDB的BGSAVE 3.1、主进程fork()操作完成后,继续响应其他请求。所有写操作依然写入AOF缓存区,并根据appendfsync策略同步到磁盘,保证原有AOF机制正确性。 3.2、由于fork()操作运用写时复制技术,所以子进程只能共享fork操作时的内存数据,由于父进程依然响应请求,Redis采用“AOF_rewrite_buf”来保存这部分新数据,防止新AOF文件生成期间丢失这部分数据。 4、子进程根据内存快照,按照命令合并规则将老的日志内容进行合并,删掉无用写操作。 每次批量写入硬盘数据量由aof-rewrite-incremental-fsync控制,默认是32MB,防止单词刷盘数据过多造成硬盘阻塞。 5.1、新AOF文件写入完成后,子进程发信息给父进程,父进程更新统计信息。 5.2、父进程把“AOF_rewrite_buf”数据写入到新的AOF文件。 5.3、使用新的AOF文件替换掉老的AOF文件,完成AOF重写操作。 注:写入操作时如果出现故障导致命令写半截,可以使用Redis-check-aof工具修复。
AOF重写触发 1、手动:客户端向服务器发送BGREWRITEAOF命令 2、自动:配置文件中的选项,自动执行BGREWRITEAOF命令
auto-aof-rewrite-min-size ,触发AOF重写所需的最小体积:只有在AOF文件的体积大于等于size时,才会考虑是否需要进行AOF重写,这个选项用于避免对体积过小的AOF文件进行重写死循环
auto-aof-rewrite-percentage ,指定触发重写所需的AOF文件体积百分比:当AOF文件的体积大于auto-aof-rewrite-min-size指定的体积,并且超过上一次重写之后的AOF文件体积的percent %时,就会触发AOF重写。(如果服务器刚刚启动不久,还没有进行过AOF重写,那么使用服务器启动时载入的AOF文件的体积来作为基准值)。将这个值设置为0表示关闭自动AOF重写
AOF重写配置项举例 auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb appendonly no / yes 当AOF文件大于64MB时候,可以考虑重写AOF文件 只有当AOF文件的增量大于起始size的100%时(就是文件大小翻了一倍),启动重写
AOF的优点: 1、安全。在开启always的时候,不会丢失任何数据。在开启everysec的时候,最多也就丢失一秒的数据。 2、重写机制。优化AOF文件 3、如果出现误操作(FIUSHAll等),只要AOF未被重写,停止服务移除AOF文件尾部即可。 4、AOF文件在发生断电等问题时也不会损坏,即使出现某条日志只写了一半的情况,也可以使用redis-check-aof工具进行修复。
AOF的缺点: 1、相同的数据集,AOF文件体积较RDB文件大了许多。 2、恢复数据库速度比RDB慢。 3、性能消耗比RDB高。
最后: 不过大多数应用场景下,建议至少开启RDB方式的数据持久化。Redis 对于数据备份是非常友好的, 因为你可以在服务器运行的时候对 RDB 文件进行复制: RDB 文件一旦被创建, 就不会进行任何修改。 当服务器要创建一个新的 RDB 文件时, 它先将文件的内容保存在一个临时文件里面, 当临时文件写入完毕时, 程序才使用 rename 原子地用临时文件替换原来的 RDB 文件。