Redis 的高性能是由其将所有数据都存储在了内存中,需要使用时直接从内存调用即可。为了使 Redis 在重启之后仍然能保证数据不丢失,需要将数据从内存同步到内存中,这一过程就是持久化

Redis 支持两种持久化方式,一种是 RDB方式,一种是 AOF方式。可以单独使用其中一种或将两种结合使用。

  • RDB (默认) 在指定的时间间隔内将内存中的数据快照写入磁盘。

  • AOF 以日志的形式记录服务器处理的每一个写操作,在Redis服务器启动之初会读取该文件来重新构建数据库,以保证启动后数据库中的数据是完整的。

一、RDB

1.1 实现步骤

  1. Redis 执行 fork 命令创建子进程。

  2. 父进程继续处理 client 请求,子进程负责将内存内容写入到临时文件。由于 OS 的写时复制机制父子进程会共享相同的物理页面,当父进程处理写请求时OS会为父进程要修改的页面创建副本,而不是写共享的页面。所以子进程的地址空间内的数据是 fork 时刻整个数据库的一个快照

  3. 当子进程将快照写入临时文件完毕后,用临时文件替换原来的快照文件,然后子进程退出。

需要注意的是,每次 RDB 都是将内存数据完整写入到磁盘一次,并不是增量的只同步脏数据。如果数据量大的话,而且写操作比较多,必然会引起大量的磁盘IO操作,可能会严重影响性能。

1.2 优势

  1. 一旦采用该方式,那么你的整个 Redis 数据库将只包含一个文件,这样非常方便备份

  2. 方便备份,我们可以很容易的将一个一个 RDB 文件移动到其他的存储介质上。

  3. RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快

  4. RDB 可以最大化 Redis 的性能(父进程在保存 RDB 文件时唯一要做的就是 fork 出一个子进程,然后这个子进程就会处理接下来的所有保存工作,父进程无须执行任何磁盘 IO 操作)。

1.3 劣势

  1. 如果你想保证数据的高可用性,即最大限度的避免数据丢失,那么 RDB 将不是一个很好的选择。 因为系统一旦在定时持久化之前发生宕机, 你就可能会丢失这之间的数据

  2. 因为 RDB 是通过 fork 子进程来协助完成持久化工作的,因此当数据集较大时,会影响服务器性能

1.4 RDB 配置

redis.conf 中可以配置和RDF相关的信息:

(1) 配置 RDB 文件位置

(2) 配置 RDB 保存时机

二、AOF

采用 AOF 方式,Redis 会将每一个收到的写命令都通过 write 函数写入到 AOF 文件中。当 Redis 重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。

AOF 的方式也同时带来了另一个问题:持久化文件会变的越来越大。例如我们调用 incr num 命令100次,文件中必须保存全部的100条命令,其实有99条都是多余的,因为要恢复数据库的状态其实文件中保存一条 set num 100 就够了。

2.1 实现步骤

  1. Redis调用fork命令创建子进程。

  2. 子进程根据内存中的数据库快照,往临时文件中写入重建数据库状态的命令。

  3. 父进程继续处理client请求,除了把写命令写入到原来的AOF文件中,同时缓存新收到的写命令。

  4. 子进程把快照内容写入写到临时文件后,子进程发信号通知父进程,然后父进程把缓存的写命令也写入到临时文件。

  5. 父进程使用临时文件替换老的AOF文件,并重命名,后面收到的写命令也开始往新的AOF文件中追加。

需要注意的是,重写AOF文件的操作并没有读取旧的AOF文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的AOF文件,这点和快照有点类似。

2.2 优势

  1. AOF 提供的三种同步策略,使得数据安全性更高。

  2. 因为 AOF 对日志文件的写入操作采用的是append 模式,因此在写入过程中即使出现宕机现象,也不会破坏日志文件已经存在的内容。

  3. 如果 AOF 日志文件过大,Redis可以自动启用 rewrite 机制,使 Redis 以 append 模式不断的将修改数据写入到老的磁盘文件中,同时 Redis 还会创建一个新的文件用于记录此期间有那些命令被执行。因此在进行 rewrite 切换时可以更好的保证数据安全性。

2.3 劣势

  1. 对于相同数量的数据集而言,AOF 文件通常要大于 RDB 文件。

  2. 根据同步策略的不同,AOF 在运行效率上往往会慢于 REB。

2.4 AOF 配置

AOF 默认是关闭的,修改配置文件 redis.conf 来打开 AOF:

AOF 具有三种同步策略,在配置文件 redis.conf 中进行配置:

除了满足同步策略来自动同步外,可以手动同步,执行命令 bgrewriteaof 即可。

下面演示下 AOF 恢复:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
wxs@ubuntu:/usr/local/redis/src$ ./redis-cli 
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> set name jitwxs #设置一个key
OK
127.0.0.1:6379> flushdb #清空数据库
OK
127.0.0.1:6379> exit
wxs@ubuntu:/usr/local/redis/src$ ps auxc | grep redis
wxs 5974 0.1 0.4 51828 8368 ? Ssl 21:23 0:00 redis-server
wxs@ubuntu:/usr/local/redis/src$ kill 5974 #停止服务
wxs@ubuntu:/usr/local/redis/src$ vim ../redis_dbfile/appendonly.aof #修改AOF文件并删除掉最后一行的flushdb命令
wxs@ubuntu:/usr/local/redis/src$ ./redis-server ../redis.conf #重新启动服务,数据被恢复
wxs@ubuntu:/usr/local/redis/src$ ./redis-cli
127.0.0.1:6379> keys *
1) "name"