Redis是内存型数据库,但是为了数据安全,就需要有“数据持久化”(就是将数据存储在磁盘上)的机制,在备份方面提供了两种工具,分别为RDB(快照)和AOF(写日志)。
RDB: 将当前内存中的数据集快照写入磁盘,也就是 Snapshot 快照(数据库中所有键值对数据)。恢复时只需要把dump.rdb这个文件放到redis的dir目录下,启动服务,将快照文件直接读到内存里。注意文件的优先级
AOF:记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。 AOF 文件中的命令全部以 Redis 协议的格式来保存,新命令会被追加到文件的末尾。 Redis 还可以在后台对 AOF 文件进行重写(rewrite),使得 AOF 文件的体积不会超出保存数据集状态所需的实际大小。
如果把redis当作缓存使用的话,你甚至可以关闭持久化功能,让数据只在服务器运行时存在。(redis4.0混合持久化)
redis> save #同步,容易阻塞。文件策略:先生成一个新的文件,待同步完成,再替换老的文件
redis> bgsave #异步,不会阻塞redis,但是会fork新进程。文件策略:先生成一个新的文件,待同步完成,再替换老的文件
save 900 1 触发条件 (建议禁用),触发bgsave
save 300 10 触发条件 (建议禁用),触发bgsave
save 60 10000 触发条件 (建议禁用),触发bgsave
全量复制,debug reload,shutdown时也是触发生成rdb文件 #触发bgsave
当 Redis 需要保存 dump.rdb 文件时, 服务器执行以下操作:
Redis 调用 fork() ,同时拥有父进程和子进程。
子进程将数据集写入到一个临时 RDB 文件中。
当子进程完成对新 RDB 文件的写入时,Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。
优点:备份文件非常紧凑,体积小,在恢复大数据集时的速度比AOF快。
缺点:不同的备份策略,可能会丢失数据,数据集比较庞大时, fork() 可能会非常耗时,造成服务器在某某毫秒内停止处理客户端; 如果数据集非常巨大,并且 CPU 时间非常紧张的话,那么这种停止时间甚至可能会更长。
redis> bgrewriteaof #手动命令触发
appendonly yes ##开启AOF功能
appendfilename "appendonly_port.aof" ##aof文件名
appendfsync everysec #always :每次更新都刷盘; everysec :每秒刷一次盘(默认);no :操作系统控制刷盘
no-appendsync-on-rewrite yes ##在进行重写时是否进行append操作。重写本身很消耗性能(IO),出于性能的考虑,建议设置成yes,设置成yes可以会丢失日志
aof-load-truncated yes ##在重启加载aof文件时,如果有错误,是否要忽略错误,建议设置成yes。
所有的写入命令追加到aof缓冲区;
AOF缓冲区根据对应appendfsync配置向硬盘做同步操作;
定期对AOF文件进行重写;
Redis重启时,可以加载AOF文件进行数据恢复
因为 AOF 的运作方式是不断地将命令追加到文件的末尾, 所以随着写入命令的不断增加, AOF 文件的体积也会变得越来越大。
举个例子, 计数器调用了 100 次 INCR, AOF 文件就需要使用 100 条记录(entry)。实际上, 只使用一条 SET 命令足以保存计数器的当前值, 其余 99 条记录都是多余的。
为了处理这种情况, Redis 支持一种有趣的特性: 可以在不打断服务客户端的情况下, 对 AOF 文件进行重建(rebuild)。
执行 BGREWRITEAOF 命令, Redis 将生成一个新的 AOF 文件, 这个文件包含重建当前数据集所需的最少命令。
Redis 2.2 需要自己手动执行 BGREWRITEAOF 命令; Redis 2.4 则可以自动触发 AOF 重写, 具体信息请查看 2.4 的示例配置文件。
实现出aof重写的方式:
redis> bgrewriteaof
auto-aof-rewrite-min-size ##设置aof文件重写需要的尺寸
auto-aof-rewrite-percentage ##设置aof文件增长率
aof_current_size ##查询aof当前尺寸(单位:字节)
aof_base_size ##aof上次启动和重要的尺寸(单位:字节)
优点:使用 AOF 持久化会让 Redis 变得非常耐久(much more durable):你可以设置不同的 fsync 策略,比如无 fsync ,每秒钟一次 fsync ,或者每次执行写入命令时 fsync 。 AOF 的默认策略为每秒钟 fsync 一次,在这种配置下,Redis 仍然可以保持良好的性能,并且就算发生故障停机,也最多只会丢失一秒钟的数据( fsync 会在后台线程执行,所以主线程可以继续努力地处理命令请求)。
缺点:对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积。根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB 。 在一般情况下, 每秒 fsync 的性能依然非常高, 而关闭 fsync 可以让 AOF 的速度和 RDB 一样快, 即使在高负荷之下也是如此。 不过在处理巨大的写入载入时,RDB 可以提供更有保证的最大延迟时间(latency)。
AOF持久化开启且存在AOF文件时,优先加载AOF文件。
AOF关闭或者AOF文件不存在时,加载RDB文件。
加载AOF/RDB文件成功后,Redis启动成功。
AOF/RDB文件存在错误时,Redis启动失败并打印错误信息。
如果 AOF 文件出错了,怎么办?
使用 Redis 附带的 redis-check-aof 程序,对原来的 AOF 文件进行修复。
$ redis-check-aof --fix
(可选)使用 diff -u 对比修复后的 AOF 文件和原始 AOF 文件的备份,查看两个文件之间的不同之处。
重启 Redis 服务器,等待服务器载入修复后的 AOF 文件,并进行数据恢复。
Redis 4.0 新增了 RDB-AOF 混合持久化格式, 这是一个可选的功能, 在开启了这个功能之后, AOF 重写产生的文件将同时包含 RDB 格式的内容和 AOF 格式的内容, 其中 RDB 格式的内容用于记录已有的数据, 而 AOF 格式的内存则用于记录最近发生了变化的数据, 这样 Redis 就可以同时兼有 RDB 持久化和 AOF 持久化的优点 —— 既能够快速地生成重写文件, 也能够在出现问题时, 快速地载入数据。
Redis 4.0 开始支持 rdb 和 aof 的混合持久化(默认关闭)。这个功能可以通过 aof-use-rdb-preamble 选项进行开启。如果把混合持久化打开,aof rewrite 的时候就直接把 rdb 的内容写到 aof 文件开头。aof 文件内容会变成如下:
RDB FORMAT |
AOF FORMAT |
这样做的好处是可以结合 rdb 和 aof 的优点, 快速加载同时避免丢失过多的数据。当然缺点也是有的, aof 里面的 rdb 部分就是压缩格式不再是 aof 格式,可读性差。
开启混合存储模式后 aof 文件加载的流程如下:
1.aof 文件开头是 rdb 的格式, 先加载 rdb 内容再加载剩余的 aof
2.aof 文件开头不是 rdb 的格式,直接以 aof 格式加载整个文件
判断 aof 文件的前面部分是否为 rdb 格式,只需要判断前 5 个字符是否是 REDIS。这个是因为 rdb 持久化开头就是 REDIS, 同时 aof 命令开头一定不会是 REDIS(命令开头都是 *)
1.fork操作很久,导致阻塞:
1.控制redis最大内存大小(maxmemory),内存越在,耗时越长。
2.使用性能更好的服务器资源
3.降低fork频率:例如放宽aof重写自动触发时机,不要全量复制
4.监控fork时长:info:latest_fork_usec 上一次执行fock时消耗的微秒数。
5.合理配置linux内存分配策略:vm.overcommit_memory=1
2.aof追加阻塞:(redis是内存数据库,在大并发时,写日志也可能需要很长的时间)
如果AOF文件fsync同步时间大于2s,Redis主进程就会阻塞,redis主进程是用来执行redis命令的,是不能阻塞的。
1.打开no-appendfsync-on-rewrite参数
2.关闭AOF
3.换更好的硬盘
4.监控:info aof_delayed_fsync aof阻塞次数
1.Redis 默认开启RDB持久化方式,在指定的时间间隔内,执行指定次数的写操作,则将内存中的数据写入到磁盘中。
2.RDB 持久化适合大规模的数据恢复但它的数据一致性和完整性较差。
3.Redis 需要手动开启AOF持久化方式,默认是每秒将写操作日志追加到AOF文件中。
4.AOF 的数据完整性比RDB高,但记录内容多了,会影响数据恢复的效率。
5.若只打算用Redis 做缓存,可以关闭持久化。
6.有主从的情况下,建议主库不做持久化,从库开启持久化。
7.建议使用redis4.0以上版本,使用混合持久化。
8.建议控制单个实例大小,体量越大,rdb生成时间越长,开销越大。同时,在从库初始化时,所需要的时间更长,网络开销更多。