Redis持久化,RDB快照和AOF日志
Redis默认是把所有的数据都存在内存中的。但是当服务器重启或程序异常崩溃时,Redis的数据就会全部丢失。因此出现了持久化的概念。持久化就是将存在内存中的数据同步到磁盘来保证持久化。
Redis 的一种持久化方式叫快照(snapshotting,RDB),另一种方式是只追加文件(append-only file, AOF)。
RDB
RDB,英文全称Redis DataBase,在指定的时间间隔,将内存中的数据写入磁盘,待恢复时再将磁盘中的数据写入内存。
Redis 可以通过创建快照来获得存储在内存里面的数据在某个时间点上的副本。Redis 创建快照之后,可以对快照进行备份,可以将快照复制到其他服务器从而创建具有相同数据的服务器副本(Redis 主从结构,主要用来提高 Redis 性能),还可以将快照留在原地以便重启服务器的时候使用。
触发方式
RDB持久化可以有自动触发和手动触发
- 自动触发:redis.conf配置文件中,比如
save 60 20
,在60s内修改20次就自动触发RDB备份。 - 手动触发:
- save:主程序中执行会阻塞当前Redis服务器,直到RDB持久化完成。期间redis不能使用。
- bgsave:fork一个子进程,异步进行快照操作。
注意:save和bgsave不能同时执行,如果bgsave命令正在执行,那么客户端发送的save命令会被拒绝执行,服务器禁止save和bgsave同时执行是为了避免父进程和子进程同时执行两个rdbSave调用,防止产生竞争条件。
保存条件
根据save选项所设置的保存条件,自动执行bgsave命令,进行间隔性数据保存的实现原理。
服务器程序会根据save选项所设置的保存条件,设置服务器状态redisServer结构的saveparams属性。
dirty计数器记录距离上次成功执行save命令后,服务器对数据状态进行了多少次修改。
lastsave属性是一个UNIX时间戳,记录了服务器上一次成功执行save命令的时间。
属性是一个数组,数组中的每个元素都是一个saveparam结构,每个saveparam结构都保存了一个save选项设置的保存条件。
AOF
与快照持久化相比,AOF 持久化的实时性更好,因此已成为主流的持久化方案。
默认情况下 Redis 没有开启 AOF(append only file)方式的持久化,可以通过 appendonly 参数开启:
appendonly yes
开启 AOF 持久化后每执行一条会更改 Redis 中的数据的命令,Redis 就会将该命令写入到内存缓存 server.aof_buf
中,然后再根据 appendfsync
配置来决定何时将其同步到硬盘中的 AOF 文件。
appendfsync的选项值
(1)Always,同步写回,每个写命令执行完立刻同步到磁盘;最多只会丢失一个命令的数据,最安全,但是效率最低;
(2)everysec,每秒写回;它最多丢失1秒的数据;
(3)no,操作系统控制的写回,每个命令执行完,存到AOF缓存中,由操作系统决定什么时候将命令写入到磁盘AOF文件中;
AOF日志实现
关系型数据库(如 MySQL)通常都是执行命令之前记录日志(方便故障恢复),而 Redis AOF 持久化机制是在执行完命令之后再记录日志。
执行完命令之后记录日志原因:
- 避免额外的检查开销,AOF 记录日志不会对命令进行语法检查;
- 在命令执行完之后再记录,不会阻塞当前的命令执行。
这样也带来了风险:
- 如果刚执行完命令 Redis 就宕机会导致对应的修改丢失;
- 可能会阻塞后续其他命令的执行(AOF 记录日志是在 Redis 主线程中进行的)。
优缺点
- 等量级的命令,AOF持久化文件要大于RDB持久化文件,RDB恢复速度更快。
- 因RDB定时备份可能丢失数据,AOF更安全,RDB生成过程比AOF开销大。
- 进行RDB持久化时如数据量过大可能影响服务性能。
由于 RDB 和 AOF 各有优势,于是,Redis 4.0 开始支持 RDB 和 AOF 的混合持久化(默认关闭,可以通过配置项 aof-use-rdb-preamble
开启)。如果把混合持久化打开,AOF 重写的时候就直接把 RDB 的内容写到 AOF 文件开头。这样做的好处是可以结合 RDB 和 AOF 的优点, 快速加载同时避免丢失过多的数据。当然缺点也是有的, AOF 里面的 RDB 部分是压缩格式不再是 AOF 格式,可读性较差。
学习参考自
javaguide、哪吒编程等博客。