一, 前言
Redis 支持两种方式的持久化, RDB 和 AOF.RDB 会根据指定的规则 "定时" 将内存中的数据存储到硬盘上, AOF 会在每次执行命令后将命令本身记录下来. 两种持久化方式可以单独使用其中一种, 但更多情况下是两种结合使用.
二, RDB
RDB 方式的持久化是通过快照完成的, 当符合一定条件的时候 Redis 会自动将内存中的所有数据生成一份副本并存储在硬盘上, 这个过程即为 "快照".Redis 会在以下四种情况下对数据进行快照:
根据配置规则进行自动快照;
用户指定 SAVE 或 BGSAVE 命令;
执行 FLUSHALL 命令;
指定复制时;
1. 根据配置规则进行自动快照
Redis 允许用户自定义快照条件, 当符合快照条件的时候, Redis 会自动进行快照操作. 进行快照的条件可以由用户的配置文件中自定义, 有两个参数构成: 时间窗口 M 和改动的键的个数 N. 每当时间 M 内被更改的键的个数大于 N 时, 即符合自动快照的条件. 例如 Redis 的安装目录中包含的样例配置文件中预置的 3 个条件:
每条快照条件占一行, 并且以 save 参数开头. 同时可以存在多个条件, 条件之间是 or 的关系. 就这个例子来说, save 900 1 的意思是在十五分钟内 (900 秒) 内有一个或者以上的键被更改则进行快照. 同理, save 300 10 表示在 300 秒内至少有十个键被修改则进行快照.
2. 用户指定 save 或 bgsave 命令
除了让 Redis 自动进行快照外, 当进行服务重启, 手动迁移以及备份时我们也会需要手动执行快照操作. Redis 提供了两个命令:
save: 当执行 save 命令的时候, Redis 同步地进行快照操作, 在快照执行地过程中阻塞所有来自客户端的请求. 当数据库中的数据比较多的时候, 这一过程会导致 Redis 较长时间不能响应, 所以要尽量避免在生产环境使用.
- 127.0.0.1:6379> save
- OK
bgsave: 需要手动执行快照时推荐使用 bgsave 命令. bgsave 命令可以在后台异步地进行快照操作, 快照地同时服务器还可以继续响应来自客户端的请求. 执行 bgsave 后 Redis 会立即返回 Background saving started 表示开始执行快照操作. 如果想知道快照是否完成, 可以通过 lastsave 命令获取最后一次成功执行快照地时间, 返回一个 unix 时间戳, 如:
- 127.0.0.1:6379> bgsave
- Background saving started
- 127.0.0.1:6379> lastsave
- (integer) 1580356962
3. 执行 flushall 命令
当执行 flushall 命令时, Redis 会清除数据库中的所有数据. 需要注意的是, 不论清空数据库的过程是否触发了自动快照的条件, 只要自动快照条件不为空, Redis 就会执行一次快照操作. 当没有自定义的自动快照条件时, 执行 flushall 则不会进行自动快照.
4. 执行复制
当设置了主从模式, Redis 会在复制初始化时进行自动快照.
5. 快照原理
理清 Redis 实现快照的过程对我们了解快照文件的特性有很大的帮助. Redis 默认会将快照文件存储在 Redis 当前进程的工作目录中的 dump.rdb 文件中, 可以通过配置 dir 和 dbfilename 两个参数分别指定快照文件的存储路径和文件名. 快照过程如下:
Redis 使用 fork 函数复制一份当前进程 (父进程) 的副本(子进程).
父进程继续接收并处理客户端发来的命令, 而子进程开始将内存中的数据写入硬盘中的临时文件.'
当子进程写入完所有的数据后会用临时文件替换旧的 RDB 文件, 至此一次快照操作完成.
通过上述过程可以发现 Redis 在进行快照的过程中不会修改 RDB 文件, 只有快照结束后才会将旧的文件替换成新的, 也就是说任何时候 RDB 文件都是完整的. 这使得我们可以通过定时备份 RDB 文件来实现 Redis 数据库的备份. RDB 文件经过压缩的二进制格式(可通过配置 rdbcompression 参数禁用压缩节省 CPU 占用), 所以占用的空间会小于内存中的数据大小, 更加利于传输.
Redis 启动后会读取 RDB 快照的文件, 将数据从硬盘载入内存. 根据数量大小和结构和服务器性能的不同, 这个时间也不同. 通常将一个记录 1000 万个字符串类型键, 大小为 1GB 的快照文件载入到内存需要 20-30 秒.
通过 RDB 方式实现持久化, 一旦 Redis 异常退出, 就会丢失最后一次快照以后更改的所有数据. 这就需要开发者根据实际情况, 通过组合设置自动快照条件的方式来将可能发生的数据损失控制在能够接受的范围内. 例如, 使用 Redis 存储缓存数据时, 丢失最近几秒的数据或者丢失最近更新的几十个键问题不大. 要是数据十分重要, 希望将损失降低到最小, 就可以使用 AOF 方式进行持久化.
三, AOF 方式
当使用 Redis 存储非临时数据时, 一般需要打开 AOF 方式持久化来降低进程中止导致的数据丢失. AOF 可以将 Redis 执行的每一条写命令追加到硬盘文件中, 这一过程显然会降低 Redis 的性能, 但是大部分情况下是可以接受的, 另外使用较快的硬盘可以提高 AOF 的性能.
1. 开启 AOF
默认情况下 Redis 没有开启 AOF 方式的持久化, 可以通过配置文件的 appendonly 参数启动, 直接修改配置文件可能没有 appendonly.aof 文件, 需要通过下列语句启动:
- 127.0.0.1:6379> config set appendonly yes
- OK
开启 AOF 持久化后每执行一条更改 Redis 中的数据的命令, Redis 就会将该命令写入硬盘中的 AOF 文件. AOF 文件的保存位置和 RDB 文件的位置相同, 都是通过 dir 参数设置的, 默认文件名是 appendonly.aof, 可以通过 appendfilename 参数修改.
2.AOF 的实现
AOF 文件以纯文本的形式记录了 Redis 执行的写命令, 例如在开启 AOF 持久化的情况下执行了如下几个命令:
- 127.0.0.1:6379> set day 1
- OK
- 127.0.0.1:6379> set day 2
- OK
- 127.0.0.1:6379> get day
- "2"
appendonly.aof 文件内的数据如下:
- *2
- $6
- SELECT
- $1
- 0
- *3
- $3
- SET
- $3
- day
- $1
- 2
从上可以看到 AOF 文件的内容正是 Redis 客户端向 Redis 发送的原始通信协议的内容. 如果执行的 Redis 命令越多那这个文件就越大, 即使内存中实际的数据可能并没有多少. 所以我们可以通过设置配置文件, 来让 Redis 在达到特定条件时自动重写 Redis 文件:
- auto-aof-rewrite-percentage 100
- auto-aof-rewrite-min-size 64mb
auto-aof-rewirte-percentage 参数的意义时当目前的 AOF 文件大小超过上一次 AOF 重写时的文件大小的百分之多少时会再次进行重写, 如果之前没有重写过, 则以启动时的 AOF 文件大小为依据.
auto-aof-rewirte-min-size 参数是限制允许重写的 AOF 文件最小的大小.
在启动 Redis 时会从 AOF 文件中逐个执行命令, 所以比 RDB 速度会慢.
3. 同步硬盘数据
虽然每次执行更改 Redis 数据库的命令时, AOF 都会记录在 AOF 文件中, 但是事实上, 由于操作系统的缓存机制, 数据并没有真正的写入硬盘, 而是进入了系统的硬盘缓存. 在默认情况下系统每 30 秒会执行一次同步操作, 以便将硬盘缓存中的内容真正写入硬盘, 所以在这之前系统异常会导致数丢失, 所以我们需要在 Redis 的配置文件中设置同步时机:
- # appendfsync always
- appendfsync everysec
- # appendfsync no
默认情况下 Redis 采用 everysec 规则, 即每秒执行一次同步. always 表示每次执行写入都同步, 这最安全却也最慢. no 表示不主动同步, 由操作系统自动来做.
Redis 允许同时开启 AOF 和 RDB 模式, 同时启动的情况下, Redis 会采用 AOF 的数据来恢复, 因为它可能丢失的数据最少.
来源: https://www.cnblogs.com/xwc1996/p/12203313.html