redis 中的 AOF 持久化和 RDB 持久化

马谦马谦马谦 Redis评论802字数 2211阅读 7 分 22 秒阅读模式

一、 AOF 持久化

1.1 实现机制

AOF(Append Only File) 是 redis 持久化方式的一种,它通过把所有 redis 执行过的命令都写入到文件来维持持久化。一旦服务崩溃,则可以重放这些命令来恢复服务数据。

例如,在 redis 上执行下面 2 条语句:

那么 AOF 文件中的内容就类似是:

当然,文件中保存不是直接的命令语句。而是按照 redis 命令请求协议保存的,除了执行的命令以外还有一些其他的内容也会保存到文件。 redis 协议是 redis 执行命令专用的一种协议,当客户端向服务端发送请求也是使用的 redis 协议,AOF 也使用 redis 协议的好处是可以直接使用 redis 协议解析库,不用再单独实现一套。

AOF 数据并不是实时写入到文件中的,而是优先保存在缓冲区。 redisServer 对象中保存了一个 aof_buf 字段,它就是 aof 命令的保存缓冲区。当执行完命令后,会先把指令保存到这里,然后根据策略把缓冲区中的内容写入到磁盘。

一个要注意的是,文件写入磁盘并不会立马刷新到文件系统,因为操作系统对系统 IO 有缓存,缓存到达一定条件后才会同步缓存到文件系统。为了避免数据没有及时写入到文件系统 (还在缓存中),AOF 提供了三种策略来同步缓存:

策略 描述
always 每处理一次事件循环,就把 aof 文件写入到文件。这种办法最稳妥,数据丢失后的恢复效果最好。
Everysec 每秒同步一次 AOF 文件缓存到文件系统。
no 不主动同步缓存,由操作系统决定什么时候写入到文件系统。

1.2 AOF 重写

当服务运行久了之后,AOF 文件会变得很大,redis 提供了 AOF 重写功能来优化 AOF 文件数据。

所做的优化就是整合指令,例如:

执行完这两个命令后,数据库保存了一个有序集合 age,里面包含了两个元素 world 和 nginx 。其中 hello 在第一个命令中加进来了,但是第二个指令又删除了,所以实际上写入 AOF 文件并不需要上面两行,只需要一行就可以完成:

AOF 重写就是基于这种策略来重写的,但是有一个要注意的地方是:在执行 AOF 写入的时候,会导致 redis 阻塞。所以一般建议是使用后台重写来完成整个 AOF 文件的重写,后台重写会新建一个子进程,避免在父进程中操作阻塞正常业务。执行后台重写的指令是 BGREWRITEAOF

二、 RDB 持久化

RDB 持久化是 redis 的第二种持久化方式,它持久化的原理是把数据库中所有键值对的二进制数据直接写入到文件。 RDB 持久化的优先级一般低于 AOF 持久化,因为 AOF 持久化的实时性高于 RDB,所以在系统启动的时候如果存在 AOF 持久化,redis 会优先通过 AOF 持久化恢复数据。

执行持久化的操作指令是 SAVEBGSAVE,一个是前台执行,一个是后台执行。和 AOF 持久化一样,前台执行会阻塞当前 redis 进程,所有客户断请求都会被阻塞,因此一般建议是用 BGSAVE,它也会新创建一个子进程来做持久化操作。 RDB 备份是全量备份。

可以在 redis.conf 中配置 RDB 相关的操作,主要有以下几个配置:

第一个配置是执行 BGSAVE 的策略,当在 secnods 秒之内执行了 changes 次操作时,会自动把改动写入到 RDB 文件。可以同时有多个 save 配置段存在,例如官方默认的配置中就有三个 save 配置:

这三个配置,只要在任意时间段内满足了任意一条就会执行 (三者互不影响,互相独立,各自备份各自的):

  1. 900 秒内执行了一次更新,BGSAVE 就会执行。
  2. 300 秒内执行了 10 次更新,BGSAVE 就会执行。
  3. 60 秒呢执行了 10000 次更新,BGSAVE 就会执行。

dbfilenamedir 指定了备份文件名和路径,执行后就会把 RDB 文件写入到这个文件中。例如,设置保存的路径为/appdata/redis/dump.rdb,执行 save 命令后,就会生成这个文件:

redis中的AOF持久化和RDB持久化-图片1

RDB 持久化文件可以使用官方的 redis-check-rdb 程序 (低版本叫 redis-check-dump) 来检测相关数据:

redis中的AOF持久化和RDB持久化-图片2

当然,这个文件只提供了基本检测功能 (即验证 rdb 文件是否合法),并不包含导出所有数据的功能。

如果需要处理实际的数据可以通过其他工具来实现,google 一下 redis rdb parser 就能看到了。

github 上也有很多,例如 https://github.com/sripathikrishnan/redis-rdb-tools

三、 AOF 和 RDB 对比

RDB 持久化 AOF 持久化
全量备份,一次保存整个数据库 增量备份,只保存新修改的数据
保存的间隔较长 保存的间隔默认一秒
更适合数据备份,默认开启 更适合用来保存数据,和一般 SQL 持久化方式一样,默认关闭
save 会阻塞,但 bgsave 或者自动不会阻塞 无论是平时还是 AOF 重写,都不会阻塞
轻重 : 重 轻重: 轻
启动优先级 : 低 启动优先级 : 高
体积 : 小 体积 : 大
恢复速度 : 快 恢复速度 : 慢
数据安全性 : 丢数据 数据安全性 : 根据策略决定

表格从 Redis 持久化 AOF 和 RDB 对比整理得来。

 
马谦马谦马谦
  • 本文由 马谦马谦马谦 发表于 2020 年 2 月 17 日 21:18:10
  • 转载请务必保留本文链接:https://www.dyxmq.cn/databases/redis/redis-persistence.html
redis中的键值淘汰策略 Redis

redis 中的键值淘汰策略

当使用的内存到达上限后,redis 提供了 6 种策略来淘汰键值: 策略 描述 volatile-lru 在所有设置了过期时间的键值中根据 LRU 算法淘汰最近最少使用的 allkeys-lru 对数据库中所有...
redis源码分析:链表实现 Redis

redis 源码分析:链表实现

一、链表定义 链表在 redis 中的使用十分广泛,例如列表的底层实现之一就是链表,包括发布、订阅等等功能都是有用到链表的。 redis 中链表在 adlist.h 和 adlist.c 中实现,只用了 300+行代码...
redis中的发布和订阅 Redis

redis 中的发布和订阅

一、发布和订阅 除了任务队列以外,redis 还有一种基于 「发布/订阅」 模式的消息传递,使得客户端可以订阅某个频道,当频道有消息产生时,会把消息传递到所有的订阅者。和列表不一样的是,发布和订阅可以是一对...
Redis小案例(二):redis实现消息队列 Redis

Redis 小案例 (二):redis 实现消息队列

一、任务队列概述 消息队列,顾名思义就是一个用来传递任务的队列。消息队列在开发中十分常见,经常用在页面后台处理需要很长时间的操作时,例如发送邮件、短信以及进行复杂数据运算操作等,这些操作通常会阻塞页面...
匿名

发表评论

匿名网友
:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:
确定

拖动滑块以完成验证