什么叫持久化?
将数据(如内存中的对象)保存到可永久保存的存储设备中。
持久化的主要应用是将内存中的对象存储在数据库中,或者存储在磁盘文件中、 XML 数据文件中等等。
redis支持两种方式的持久化,RDB和AOF。前者会根据指定的规则,“定时”将内存中的数据存储在硬盘上,后者在每次执行命令时将命令本身记录下来。
RDB:
以下情况会对数据进行快照:
(1) 根据配置规则进行自动快照;
在redis.conf文件中配置如下参数:
save 900 1(900秒内有一个或一个以上的键值被更改则进行快照)
save 300 10
save 60 10000
save ""(禁用RDB)
(2) 用户执行SAVE或BGSAVE命令;
当执行SAVE命令时,Redis主进程会进行快照操作,在快照执行的过程中会阻塞所有来自客户端的请求。线上慎用此命令。需要手动执行快照时,推荐使用BGSAVE命令。BGSAVE会fork出一个子进程,子进程调用rdbSave方法,保存完毕之后,向主进程发送信号,通知保存已完成。可以通过LASTSAVE命令获取最后一次成功执行快照的时间,返回结果是Unix时间戳。
SAVE为同步操作,BGSAVE为异步操作。
(3) 执行FLUSHALL命令;
当执行FLUSHALL命令时,Redi会清空数据库中所有数据,只要自动快照条件不为空(save ""),Redis就会执行一次快照操作。
(4) 执行复制时;
主从模式,从数据库启动时,主数据库会执行一次快照操作,即使没有设置rdb持久化,也会执行。
(5) 执行SHUTDOWN命令;
在持久化被打开的情况下,执行SHUDOWN会执行一次快照操作。
原理:
Redis默认会将快照文件存储在Redis当前进程目录中的dump.rdb文件中,可以通过配置dir和dbfilename两个参数指定快照文件存储路径和文件名。快照过程如下:
(1) Redis使用fork函数复制一份当前主进程的副本(子进程);
(2) 主进程继续接收并处理客户端发来的请求,而子线程开始将内存中的数据写入硬盘中的临时文件;
(3) 当子进程写入完所有数据后会用该临时文件替换旧的RDB文件。
RDB文件是经过压缩的二进制格式,可以配置rdbcompression参数禁用。
通过RDB方式实现持久化,一旦Redis异常退出,就会失去最后一次快照以后更改的数据。
AOF:
AOF可以将Redis执行的每一条写命令追加到硬盘文件中。
默认情况下Redis没有开启AOF方式的持久化,可以通过appendonly参数启用:appendonly yes。文件存储的路径与RDB文件位置相同,通过dir参数设置,默认文件名是appendonly.aof,可以通过appendfilename参数修改:appendfilename appendonly.aof。
设置同步方式:
(1) appendfsync always # 每次有数据修改发生时都会写入AOF文件(安全但是费时)。
(2) appendfsync everysec # 每秒钟同步一次,该策略为AOF的缺省策略。
(3) appendfsync no # 从不同步。高效但是数据不会被持久化。
重写:
随着执行的命令越来越多,AOF文件大小也会越来越大。每达到一定条件或者手动执行BGREWRITEAOF,Redis会对AOF文件进行自动重写,重写后的新文件包含了重写前最小的命令集合,设置条件如下:
auto-aof-rewrite-percentage 100 #参数是当前AOF文件大小超过上一次重写时的AOF文件大小的百分之X时会再次进行重写。
auto-aof-rewrite-min-size 64mb #允许重写的最小aof文件大小,避免了达到约定百分比但尺寸仍然很小的情况还要重写
no-appendfsync-on-rewrite yes #在日志重写时,不进行命令追加操作,而只是将其放在缓冲区里,避免与命令的追加造成DISK IO上的冲突
AOF 重写和 RDB 创建快照一样,都巧妙地利用了写时复制机制。
以下是 AOF 重写的执行步骤:
(1) Redis 执行 fork() ,现在同时拥有父进程和子进程。
(2) 子进程开始将新 AOF 文件的内容写入到临时文件。
(3) 对于所有新执行的写入命令,父进程一边将它们累积到一个内存缓存中,一边将这些改动追加到现有 AOF 文件的末尾: 这样即使在重写的中途发生停机,现有的 AOF 文件也还是安全的。
(4) 当子进程完成重写工作时,它给父进程发送一个信号,父进程在接收到信号之后,将内存缓存中的所有数据追加到新 AOF 文件的末尾。
(5) Redis 原子地用新文件替换旧文件,之后所有命令都会直接追加到新 AOF 文件的末尾。
RDB和AOF文件损坏如何修复?
如果aof或rdb文件语法有误,可以使用如下两条命令来修复。
aof修复命令:redis-check-aof --fix appendonlly.aof
rdb修复命令:redis-check-rdb --fix dump.rdb
怎样从 RDB 方式切换为 AOF 方式?
在不重启的情况下,从 RDB 切换到 AOF :
(1) 为最新的 dump.rdb 文件创建一个备份、将备份放到一个安全的地方。
(2) 执行以下两条命令:
redis-cli config set appendonly yes
redis-cli config set save “”
(3) 确保写命令会被正确地追加到 AOF 文件的末尾。执行的第一条命令开启了 AOF 功能:Redis 会阻塞直到初始 AOF 文件创建完成为止,之后 Redis 会继续处理命令请求,并开始将写入命令追加到 AOF 文件末尾。
(4) 执行的第二条命令用于关闭 RDB 功能。这一步是可选的,如果你愿意的话,也可以同时使用 RDB 和 AOF 这两种持久化功能。
PS:别忘了在 redis.conf 中打开 AOF 功能!否则服务器重启后,之前通过 CONFIG SET 命令设置的配置就会被遗忘,程序会按原来的配置来启动服务器。
RDB 和 AOF 之间的相互作用
BGSAVE 执行的过程中, 不可以执行 BGREWRITEAOF 。 反过来说, 在 BGREWRITEAOF 执行的过程中, 也不可以执行 BGSAVE 。
这可以防止两个 Redis 后台进程同时对磁盘进行大量的 I/O 操作。
如果 BGSAVE 正在执行, 并且用户调用 BGREWRITEAOF 命令, 那么服务器将向用户回复一个 OK 状态, 并告知用户, BGREWRITEAOF 已经被预定执行: 一旦 BGSAVE 执行完毕, BGREWRITEAOF 就会正式开始。
当 Redis 启动时, 如果 RDB 持久化和 AOF 持久化都被打开了, 那么程序会优先使用 AOF 文件来恢复数据集, 因为 AOF 文件所保存的数据通常是最完整的。
网友评论