文章目录
Redis高可用详解:持久化技术及方案选择
redis4.0深入持久化
面试必问的 Redis:RDB、AOF、混合持久化
Redis 的持久化机制有哪几种
RDB、AOF、混合持久化(Redis4.0引入)
持久化之RDB
原理: RDB持久化是将 Redis 在内存中的数据库状态(数据库的键值对等信息)生成快照保存到磁盘里面,生成的 RDB 文件是经过压缩的二进制文件。
触发机制
触发命令: save
、bgsave
(background save)
save
:阻塞当前Redis服务器,直到RDB过程完成为止,对于内存 比较大的实例会造成长时间阻塞,线上环境不建议使用。bgsave
:Redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短。
Redis内部所有的涉 及RDB的操作都采用bgsave的方式,而save命令已经废弃。
自动触发RDB的持久化 机制:
save m n
表示m
秒内数据集存在n
次修改时,自动触发bgsave
。
从节点执行全量复制操作时,主节点自动执行bgsave生成RDB文件并发送给从节点。
默认情况下执行shutdown
命令时,如果没有开启AOF
持久化功能则自动执行bgsave
。
save 900 1 # 900秒内有1个key发生了变化,则触发保存RDB文件
save 300 10 # 300秒内有10个key发生了变化,则触发保存RDB文件
save 60 10000 # 60秒内有10000个key发生了变化,则触发保存RDB文件
RDB持久化流程
RDB文件压缩
Redis默认采用LZF算法对生成的RDB文件做压缩处理,压缩后的文件远远小于内存大小,默认开启,可以通过参数config set rdbcompression{yes|no}
动态修改。
虽然压缩RDB会消耗CPU,但可大幅降低文件的体积,方便保存到硬盘或通过网络发送给从节点,因此线上建议开启。
RDB的优缺点
优点:
- RDB是一个紧凑压缩的二进制文件。非常适用于备份,用于灾难恢复。
- Redis加载RDB恢复数据远远快于AOF的方式。因为AOF文件中存放的是操作命令。
缺点:
- 一旦Redis异常退出,就会丢失最后一次快照以后更改的数据,这样就会造成数据不完整性或者不一致。
- 不能做到实时持久化,每次都会创建子线程,进行备份数据时,会生成临时文件,属于重量级操作,频繁执行成本过高。
- RDB二进制文件可能出现新老版本不兼容问题。
持久化之AOF
原理: AOF持久化策略是将发送到Redis服务端的每一条目录都记录下来,并保存到硬盘中的AOF文件。
配置方式:(默认不开启)
AOF 持久化功能的实现可以分为三个步骤: 命令追加、文件写入、文件同步。
命令追加: 当 AOF 持久化功能打开时,服务器在执行完一个写命令之后,会将被执行的写命令追加到服务器状态的 aof 缓冲区(aof_buf
)的末尾。
文件写入与文件同步: 为什么将 aof_buf
的内容写到磁盘上需要两步操作,这边简单解释一下。
Linux 操作系统中为了提升性能,使用了页缓存(page cache)。当我们将 aof_buf 的内容写到磁盘上时,此时数据并没有真正的落盘,而是在 page cache 中,为了将 page cache 中的数据真正落盘,需要执行 fsync / fdatasync 命令来强制刷盘。这边的文件同步做的就是刷盘操作,或者叫文件刷盘可能更容易理解一些。
aof 缓冲区的内容先写入到 Linux 的页缓存,然后通过 fsync
命令强制同步到磁盘。
AOF文件重写策略:
重写是优化AOF文件,可以使用BGREWRITEAOF
命令来重写AOF文件。
AOF持久化会保存每一条被执行的写命令,那么随着服务器运行时间的增长,对应的AOF文件内容会越来越多,文件也会越来越大,从而对服务器造成影响,为此,Redis提供了文件重写的功能,来解决AOF文件过大问题,它是通过重写程序aof_write实现的。
AOF文件中重写后全部都是Redis主进程中全部数据的写命令。
为什么要重写呢?
- 因为同一个key可能会设置两次value值,这时在AOF中有两条记录,重写后只会保存后面的记录,节省数据恢复的时间。
- 进程内已经超时的数据不再写入文件。
- 多条写命令可以合并为一个,如:
lpush list a、lpush list b、lpush list c
可以转化为:lpush list a b c
。 - 如果你对一个计数器调用了 100 次 INCR , 那么仅仅是为了保存这个计数器的当前值, AOF 文件就需要使用 100 条记录。重写后使用一条 SET 命令已经足以保存计数器的当前值了。
重写后的AOF文件为什么可以变小?
- 进程内已经超时的数据不再写入文件。
- 新的AOF文件只保留最终数据的写入命令。
AOF重写降低了文件占用空间,除此之外,另一个目的是:更小的AOF文件可以更快地被Redis加载。
为什么要设计两种持久化方式:
因为RDB方式存在的缺陷,如果在没有触发快照的情况下,机器宕机,数据会丢失。
AOF 在过去曾经发生过这样的 bug : 因为个别命令的原因,导致 AOF 文件在重新载入时,无法将数据集恢复成保存时的原样。
总结: 作为缓存可以不用持久化,大不了走DB,作为内存数据库一定要持久化了。
RDB和AOF区别
RDB是全量的,AOF是实时的。
RDB适合备份,默认开启。
AOF默认不开启,如果AOF开启,Redis启动时会从AOF文件恢复数据,否则从RDB文件恢复数据。
Redis重启时加载持久化文件
在Redis的实际使用过程中,可以将RDB持久化和AOF持久化同时使用,RDB用于灾难数据恢复(快速的数据恢复),AOF用于服务器重启数据恢复(AOF保证据不丢失)。
Redis重启时加载持久化文件的顺序: 如果同时启用了 AOF 和 RDB,Redis 重新启动时,会使用 AOF 文件来重建数据集,因为通常来说, AOF 的数据会更完整。
流程说明:
- 1、AOF持久化开启且存在AOF文件时,优先加载AOF文件;打印日志:
DB loaded from append only file: 5.841 seconds
- 2、AOF关闭或者AOF文件不存在时,加载RDB文件;打印日志:
DB loaded from disk: 5.586 seconds
- 加载AOF/RDB文件成功后,Redis启动成功。
- 3、AOF/RDB文件存在错误时,Redis启动失败并打印错误信息。
混合持久化的实现原理、优缺点
描述: 混合持久化并不是一种全新的持久化方式,而是对已有方式的优化。混合持久化只发生于 AOF 重写过程。使用了混合持久化,重写后的新 AOF 文件前半段是 RDB 格式的全量数据,后半段是 AOF 格式的增量数据。
整体格式为: [RDB file][AOF tail]
开启: 混合持久化的配置参数为 aof-use-rdb-preamble
,配置为 yes
时开启混合持久化,在 Redis4 刚引入时,默认是关闭混合持久化的,但是在 Redis5 中默认已经打开了。
关闭: 使用 aof-use-rdb-preamble no
配置即可关闭混合持久化。
混合持久化本质是通过 AOF 后台重写(bgrewriteaof
命令)完成的,不同的是当开启混合持久化时,fork
出的子进程先将当前全量数据以 RDB
方式写入新的 AOF
文件,然后再将 AOF
重写缓冲区(aof_rewrite_buf_blocks
)的增量命令以 AOF
方式写入到文件,写入完成后通知主进程将新的含有 RDB
格式和 AOF
格式的 AOF
文件替换旧的的 AOF
文件。
优点: 结合 RDB 和 AOF 的优点, 更快的重写和恢复。
缺点: AOF 文件里面的 RDB 部分不再是 AOF 格式,可读性差。
RDB、AOF、混合持久,应该用哪一个
如果想尽量保证数据安全性, 你应该同时使用 RDB 和 AOF 持久化功能,同时可以开启混合持久化。
如果你非常关心你的数据, 但仍然可以承受数分钟以内的数据丢失, 那么你可以只使用 RDB 持久化。
如果你的数据是可以丢失的,则可以关闭持久化功能,在这种情况下,Redis 的性能是最高的。