您现在的位置是:首页 > 文章 > Redis 的持久化机制 网站文章

Redis 的持久化机制

孙玉超 2021-03-27 15:14:31 0 评论 848 浏览 0 收藏 0


Redis 作为一个基于内存的高性能数据库,必须的有对应的持久化机制,否则一旦出现宕机,那数据可就全完了。即使有持久化机制,遇到宕机也要妥善处理,恢复数据,所以本篇文章探讨 Redis 的持久化机制


RDB 机制


RDB 是 Redis 启动默认并且开启的持久化机制,它是按照某种规则在指定的时间间隔内将内存中的数据写到磁盘,文件默认命名为 dump.rdb 。当 Redis 启动时,也会默认加载这个 dump.rdb 来将磁盘数据读取到内存中。可以查阅 redis.conf 文件,搜索 SNAPSHOTTING ,下面一段就是 RDB 的注释。它遵循一种规则,save <seconds> <changes> ,在指定时间间隔内,如果对数据进行了指定次数的修改,那么当时间间隔到达时将会做一次持久化。注意,并不是修改次数到达就进行持久化,而是满足了修改次数,并且到了指定的时间间隔,才会进行持久化。默认情况下,Redis 给我们设置了三个值

save 900 1        #如果在 900 秒内,至少修改了 1 次,那么当900秒之后的那个时间点到达将会进行持久化
save 300 10       #如果在 300 秒内,至少修改了 10 次.......
save 60 10000     #......

这样当有数据变更的时候,redis 的目录下会生成一个名为 dump.rdb 的文件,5.0.5 版本的 redis ,此文件目录为 redis-5.0.5/src/dump.rdb 。这个文件名也可以在配置文件中修改,当然如果你高兴甚至还可以关掉 RDB 的持久化机制,但没必要。


RDB 的原理是,Redis 会单独创建一个子进程来进行持久化,先把数据写到一个临时文件,等持久化过程结束,再用这个临时文件替换掉上次持久化产生的 rdb 文件。整个过程中主进程不进行 IO 操作,这就确保了很高的性能。但是这种机制其实会出现一个问题,比如我们设置的 save 60 10000 。  60 秒内如果修改了 10000 次,就进行持久化。假设我们 50 秒内修改了 10000 次,按道理再过 10 秒钟就会持久化,但是不知道造了什么孽此时 Redis 宕机了,挂了。那么就没有持久化,那就完蛋了,这 10000 次的修改的数据都没了。所以 rdb 机制会有一个问题,总是会导致最后一次持久化可能失败,除非你能保证 Redis 永远不挂,但这是不可能的。此时就引出了 Redis 给我们提供的第二种持久化机制 AOF。


AOF 机制


AOF 机制默认是关闭的,在 redis.conf 文件中搜索 APPEND ONLY MODE ,下面这一段就是介绍 AOF 的。只要 appendonly 的 no 改成 yes 即可,默认的文件名是 appendonly.aof ,和 dump.rdb 文件在同一目录下。

#appendonly no 
appendonly yes

如果开启了 AOF 机制,当有数据修改时,AOF 是按照客户端发送的修改/新增/删除命令以日志追加的形式将命令追加到 appendonly.aof 中。Redis 在重启时也会读取该文件来将磁盘数据恢复到内存,而不是读取原来的 dump.rdb 文件,其实就是将 appendonly.aof 中的命令重新执行一遍来完成恢复工作。虽然重启时 Redis 不会读取 dump.rdb ,但是只要 RDB 机制没有关,那么 RDB 同步机制还是可以正常进行。redis.conf 中其实已经说明了这一点:AOF and RDB persistence can be enabled at the same time without problems 。


AOF 的原理是,收到客户端的修改/新增/删除指令后进行一些校验,确保此条命令没有问题后将该指令文本保存到 appendonly.aof 中。这个过程并不是直接持久化,中间其实是先把指令写到一个内存缓存中,等待操作系统内核调用 fsync 函数将缓存中的数据写到磁盘。所以我们可以猜测一个场景,就是当 AOF 写日志到缓存而没有同步到磁盘的时候,Redis 如果挂了,那这块数据就丢了。所以 Redis 给我们提供了一个参数来设置 fsync 从内存缓存往磁盘写数据的频率。

#appendfsync always #每次都同步,保证数据不会丢失,但会慢。这样就相当于每条指令都要进行 IO 落盘...
appendfsync everysec #每一秒同步,系统默认同步策略
#appendfsync no #不主动同步,由操作系统决定,快,但数据容易丢失

我们为了权衡利弊,默认使用的是每秒把内存缓存的数据同步到 appendonly.aof 文件。这样最差的情况最多也只会丢失一秒的数据。


当 Redis 服务器存储的数据越来越多,或者说对数据的操作越来越多,势必会造成 appendonly.aof 文件越来越大,几个 G 甚至几十个 G 也有可能。而且这样如果重启一次 Redis ,那么恢复的时间会很久很久。所以,Redis 给我们提供了一种重写机制,当 appendonly.aof 文件大小到达一定值,会开启一个子进程来遍历内存,将数据转换成一系列 Redis 指令,而不是记录所有原先的指令,将转换后的指令追加到新的 appendonly.aof 文件中,再将这个文件替换原来的,然后把这个重写机制操作期间发生的客户端修改命令再追加到新的 appendonly.aof 文件末尾,这样就完成了。关于什么时候触发重写机制,redis.conf 给我们提供了几个配置

auto-aof-rewrite-percentage 100 #aof文件大小超过上次重写时文件大小的百分之几开始重写,如果之前没有写过,则根据启动时文件大小。
auto-aof-rewrite-min-size 64mb #限制允许重写时的最小文件大小。


虽然有了 AOF 重写机制让这种持久化方式更加友好,但是相对于 RDB 快照的模式,Redis 重启的话,AOF 仍然很慢。所以 Redis 4.0 版本之后给我提供了混合持久化方式。来解决 Redis 重启较慢的问题。


Redis 4.0 混合持久化


Redis 4.0 之后,如果开启了 AOF 机制,那么混合持久化是默认开启的。

aof-use-rdb-preamble yes #开启混合持久化

它的工作原理是当 AOF 机制进行重写时,把 dump.rdb 文件的内容写在新的 appendonly.aof 文件开头,增量日志写在结尾。这样一来,当 Redis 重启时大部分数据都在 dump.rdb 文件中,恢复数据的速度将会大大提高。




转载请注明出处:转载请注明出处

上一篇 : RabbitMQ 的工作流程和几种交换机的工作模式 下一篇 : RabbitMQ 消息可靠投递和成功消费

留言评论

所有回复

暮色妖娆丶

96年草根站长,2019年7月接触互联网踏入Java开发岗位,喜欢前后端技术。对技术有强烈的渴望,2019年11月正式上线自己的个人博客