目录
什么是持久化?
RDB(定期备份)
触发机制
bgsave命令的运作流程
RDB文件的处理
RDB文件
RDB的优缺点
AOF(实时备份)
AOF工作流程
AOF 缓冲区同步⽂件策略
AOF重写机制
AOF重写流程
Redis根据持久化文件进行数据恢复
混合持久化
什么是持久化?
通过前面几篇文章的介绍我们知道Reids是把数据存储在内存中的,但是内存中的数据是不持久的,因为当发生极端异常情况时,内存中的数据是无法保留的,要想能够做到持久,就需要让Redis制定一定的策略把数据存放到磁盘中;在Redis重启的时候,将数据在恢复到内存中。
Redis ⽀持 RDB 和 AOF 两种持久化机制,持久化功能有效地避免因进程退出造成数据丢失问题,
当下次重启时利⽤之前持久化的⽂件即可实现数据恢复。
RDB(定期备份)
RDB(Redis Datebase) 持久化是把当前进程数据⽣成快照保存到硬盘的过程,触发 RDB 持久化过程分为⼿动触发和
⾃动触发。
触发机制
手动触发
程序员通过Reids客户端,执行待定的命令,来触发快照生成;
⼿动触发分别对应 save 和 bgsave 命令:
- save 命令:阻塞当前 Redis 服务器,直到 RDB 过程完成为⽌,对于内存⽐较⼤的实例造成⻓时间阻塞,基本不采⽤。(这种行为类似于执行keys *的后果,所以一般不建议使用save)
- bgsave 命令:Redis 进程执⾏ fork 操作创建⼦进程,RDB 持久化过程由⼦进程负责,完成后⾃动结束。阻塞只发⽣在 fork 阶段,⼀般时间很短。
bgsave命令的运作流程
bgsave是主流的RDB持久化方式
- 执⾏ bgsave 命令,Redis ⽗进程判断当前进是否存在其他正在执⾏的⼦进程,如 RDB/AOF ⼦进程,如果存在 bgsave 命令直接返回。
- ⽗进程执⾏ fork 创建⼦进程,fork 过程中⽗进程会阻塞,通过 info stats 命令查latest_fork_usec 选项,可以获取最近⼀次 fork 操作的耗时,单位为微秒。
- ⽗进程 fork 完成后,bgsave 命令返回 "Background saving started" 信息并不再阻塞⽗进程,可以继续响应其他命令。
- ⼦进程创建 RDB ⽂件,根据⽗进程内存⽣成临时快照⽂件,完成后对原有⽂件进⾏原⼦替换。执⾏ lastsave 命令可以获取最后⼀次⽣成 RDB 的时间,对应 info 统计的 rdb_last_save_time 选项。
- 进程发送信号给⽗进程表⽰完成,⽗进程更新统计信息。
RDB文件的处理
- 保存:RDB ⽂件保存再 dir 配置指定的⽬录(默认 /var/lib/redis/)下,⽂件名通过 dbfilename配置(默认 dump.rdb)指定。可以通过执⾏ config set dir {newDir} 和 config set dbfilename{newFilename} 运⾏期间动态执⾏,当下次运⾏时 RDB ⽂件会保存到新⽬录。
- 压缩:Redis 默认采⽤ LZF 算法对⽣成的 RDB ⽂件做压缩处理,压缩后的⽂件远远⼩于内存⼤⼩,默认开启,可以通过参数 config set rdbcompression {yes|no} 动态修改。
- 校验:如果 Redis 启动时加载到损坏的 RDB ⽂件会拒绝启动。这时可以使⽤ Redis 提供的 redis-check-dump ⼯具检测 RDB ⽂件并获取对应的错误报告。
RDB文件
说明:
- RDB ⽂件保存再 dir 配置指定的⽬录(默认 /var/lib/redis/)下的
- 此文件是一个通过LZF算法生成的二进制文件,在这个文件的末尾进行修改的时候可能不会早场影响,在这个文件的中间或者开头进行修改的时候可能会造成Reids客户端无法重启;我们可以使用vim打开看看,但是切记不要进行任何的修改
- 在子进程根据快照生成新的文件时,旧的文件依旧存在;当新的临时文件成功生成后,才会删除旧的文件,将新的文件改为配置文件;这样子进程进行重写时发生意外;
- 执行依次flushall及对Reids客户端的key进行了清理,又对dump.rdb进行了清理;
验证save命令
当我们插入少量的数据时,可以执行save命令;因为它基本不会阻塞,会在一瞬间完成;根据查看同一个文件的inode,我们可以发现执行save命令前后文件的inode是不同的;使用vim打开文件查看时我们也是可以发现几个关键词我们可以看懂的。
验证bgsave命令
自动触发
在Redis的配置文件中可以设置让Redis每隔过长时间/每产生多少次修改就触发,这个触发机制才是在实战中有价值的;
使⽤ save 配置。如 "save m n" 表⽰ m 秒内数据集发⽣了 n 次修改,⾃动 RDB 持久化。
从节点进⾏全量复制操作时,主节点⾃动进⾏ RDB 持久化,随后将 RDB ⽂件内容发送给从结点。
执⾏ shutdown 命令关闭 Redis 时,执⾏ RDB 持久化。
RDB的优缺点
- RDB 是⼀个紧凑压缩的⼆进制⽂件,代表 Redis 在某个时间点上的数据快照。⾮常适⽤于备份,全量复制等场景。⽐如每 6 ⼩时执⾏ bgsave 备份,并把 RDB ⽂件复制到远程机器或者⽂件系统中(如 hdfs)⽤于灾备。
- Redis 加载 RDB 恢复数据远远快于 AOF 的⽅式。
- RDB ⽅式数据没办法做到实时持久化 / 秒级持久化。因为 bgsave 每次运⾏都要执⾏ fork 创建⼦进程,属于重量级操作,频繁执⾏成本过⾼。
- RDB ⽂件使⽤特定⼆进制格式保存,Redis 版本演进过程中有多个 RDB 版本,兼容性可能有⻛险
AOF(实时备份)
AOF(Append Only File)持久化:以独⽴⽇志的⽅式记录每次写命令,重启时再重新执⾏ AOF
⽂件中的命令达到恢复数据的⽬的。AOF 的主要作⽤是解决了数据持久化的实时性,⽬前已经是Redis 持久化的主流⽅式。
AOF默认一般是关闭状态,需要修改配置文件并重启Redis,才能开启AOF功能;当 开启AOF的时候RDB就不生效了,启动的时候不在读取rdb文件内容了;
AOF是一个文本文件每次进行的操作,都会被记录到文本文件中,通过一些特殊的符号作为分隔符,来对命令的细节做出区分;
AOF机制并不是直接让工作线程把数据写入硬盘,而是写入一个内存中的缓冲区,积累一波后在统一写入硬盘;因此这也是AOF机制的一个弊端:当进程突然挂掉了,或者主机掉线了;缓冲区内的数据还没来得及写入硬盘中的数据是会丢失的;
AOF机制是每次把新的操作写入到原有问价的末尾,属于顺序写入;因为在磁盘上读写数据,顺序读写的速度时比较快的;
AOF工作流程
- 所有的写⼊命令会追加到 aof_buf(缓冲区)中。
- AOF 缓冲区根据对应的策略向硬盘做同步操作。
- 随着 AOF ⽂件越来越⼤,需要定期对 AOF ⽂件进⾏重写,达到压缩的⽬的。
- 当 Redis 服务器启动时,可以加载 AOF ⽂件进⾏数据恢复。AOF缓冲区文件同步策略
AOF 缓冲区同步⽂件策略
刷新频率越高,性能影响越大,同时数据的可靠性就高
刷新频率越低,性能影响越小,数据的可靠性越低
可配置值 | 说明 |
always | 命令写⼊ aof_buf 后调⽤ fsync 同步,完成后返回 |
everysec | 命令写⼊aof_buf 后只执⾏ write 操作,不进⾏fsync。每秒由同步线程进⾏ fsync。 |
no | 命令写⼊ aof_buf 后只执⾏ write 操作,由 OS 控制fsync 频率。 |
AOF重写机制
随着命令不断写⼊ AOF,⽂件会越来越⼤,为了解决这个问题,Redis 引⼊ AOF 重写机制压缩⽂
件体积。AOF ⽂件重写是把 Redis 进程内的数据转化为写命令同步到新的 AOF ⽂件。
原因如下:
- 进程内已超时的数据不再写⼊⽂件。
- 旧的 AOF 中的⽆效命令,例如 del、hdel、srem 等重写后将会删除,只需要保留数据的最终版本。
- 多条写操作合并为⼀条,例如 lpush list a、lpush list b、lpush list 从可以合并为 lpush list a bc。
例如:当我们执行多条set命令插入数据的时候,是不是可以将这多条命令压缩成一条set命令;又或者我们执行多条del命令删除数据的时候,按照上面的思想也可以将多条del命令压缩成一条del命令;本质就是压缩指令。
这样做较⼩的 AOF ⽂件⼀⽅⾯降低了硬盘空间占⽤,⼀⽅⾯可以提升启动 Redis 时数据恢复的速度
AOF 重写过程可以⼿动触发和⾃动触发:
⼿动触发:调⽤ bgrewriteaof 命令。
⾃动触发:根据 auto-aof-rewrite-min-size 和 auto-aof-rewrite-percentage 参数确定⾃动触发时
机。
auto-aof-rewrite-min-size:表⽰触发重写时 AOF 的最⼩⽂件⼤⼩,默认为 64MB。
auto-aof-rewrite-percentage:代表当前 AOF 占⽤⼤⼩相⽐较上次重写时增加的⽐例。
AOF重写流程
1.执⾏ AOF 重写请求
如果当前进程正在执⾏ AOF 重写,请求不执⾏。如果当前进程正在执⾏ bgsave 操作,重写命令
延迟到 bgsave 完成之后再执⾏。
2.⽗进程执⾏ fork 创建⼦进程。
3.重写
- 主进程 fork 之后,继续响应其他命令。所有修改操作写⼊ AOF 缓冲区并根据 appendfsync 策略同步到硬盘,保证旧 AOF ⽂件机制正确。
- ⼦进程只有 fork 之前的所有内存信息,⽗进程中需要将 fork 之后这段时间的修改操作写⼊AOF 重写缓冲区中。
4.⼦进程根据内存快照,将命令合并到新的 AOF ⽂件中。
5.⼦进程完成重写 a.新⽂件写⼊后,⼦进程发送信号给⽗进程。
b. ⽗进程把 AOF重写缓冲区内临时保存的命令追加到新 AOF ⽂件中。
c. ⽤新 AOF ⽂件替换⽼ AOF ⽂件。
Redis根据持久化文件进行数据恢复
混合持久化
由于AOF本来是按照文本的方式来写入文件的,但是文本的方式写文件后续加载的成本是比较高的;因此Reids结合RDB和AOF的特点引入了“混合持久化的方式;这种方式按照AOF的方式将每一个请求/操作都记录入文件;再触发AOF重写后,就会把当前内存的状态按照AOF文本的方式追加到文件的后面;
今天对Resid持久化的分享到这就结束了,希望大家读完后有很大的收获,也可以在评论区点评文章中的内容和分享自己的看法;个人主页还有很多精彩的内容。您三连的支持就是我前进的动力,感谢大家的支持!!!