这篇笔记会介绍Redis的各个持久化选项,这些选项可以让用户将自己的数据存储到硬盘上面。接着将介绍如何通过Redis的 复制特性,把不断更新的数据副本存储到附加的机器上面,从而提升系统的性能和数据的可靠性。现在我们来看看Redis如何将数据存储到硬盘里面,使得数据在Redis重启之后仍然存在的。

数据持久化

redis提供了两种不同的持久化方法将数据持久化到硬盘里面。一种叫做快照(snapshoting), 它可以将某一时刻的所有数据都写入硬盘里面。另一中方法叫做之追加文件(append-only file, AOF), 他会在执行写命令时, 将被执行的写命令复制到硬盘里面。这两中方法既可以同时使用,也可以单独使用。

持久化配置选项

1
2
3
4
5
6
7
8
9
10
11
12
13
# 持久化快照
save 60 1000
stop-writes-on-bgsave-error no
rdbcompression yes
dbfilename dump.rdb
# AOF
appendonly no
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# 共享选项,这个选项决定了快照文件和AOF文件的保存位置
dir ./

​ conf-4.1

快照持久化

根据配置,快照将被写入dbfilename选项指定的文件里面,并存储在dir选项指定的路径里面。一般情况下,系统崩溃后,将丢失最近一次创建快照之后的数据。

创建快照的方式有以下几种。

  • 客户端通过Redis发送BGSAVE命令来创建一个快照。对于BGSAVE,Redis会fork一个子进程来负责创建快照,而父进程则继续处理命令请求。
  • 也可以通过Redis发送SAVE命令来创建一个快照,不过这时Redis服务器在创建快照完毕之前无法响应其他命令,故此命令不常用。
  • 如果用户设置可save配置选项,比如save 60 1000, 那么从最近一次创建快照之后算起,当”60秒内有1000次写入“这个条件满足时, Redis会自动出发BGSAVE命令。如果配置了多个save选项,则任意个满足就会 出发BGSAVE命令。
  • 当Redis通过shutdown命令接受到关闭 服务器的请求时,或者收到标准term信号时,会执行一个SAVE命令,阻塞所有客户端,不在执行客户单发送的命令,并在save命令完成之后再关闭服务器。
  • 当一个redis服务器链接另一个redis服务器,并向对方发送sync命令来开始一次复制操作的时候,如果主服务器目前没有在执行bgsave操作,或者主服务器并非刚刚执行完bgsave操作,那么主服务器就会执行bgsave命令。

AOF持久化

简单来说,AOF持久化将被执行的写命令写到AOF文件按的末尾,一次来记录数据发生的变化。因此,Redis只需从头到尾重新执行一次AOF文件包含的写命令,就可以恢复数据。

AOF可以通过配置 appendonly yes来打开。

appendfsync配置选项对AOF文件的频率进行设置:

选项 同步频率
always 每个写命令都要同步写入硬盘。这样会严重降低Redis的速度
everysec 每秒执行一次,显式的将多个写命令同步到硬盘(推荐)
no 让操作系统来决定何时进行同步

AOF缺点

  1. 因为Redi会不断的将被执行的写命令记录到AOF文件里面,随着redis的不断运行,AOF文件按会不断的增大,甚至可能会用完硬盘的所有可用空间。
  2. 因为redis在重启之后需要通过执行AOF中所有的写命令来恢复数据,所以如果AOF文件非常大,那么还原操作执行的时间会非常长。

为了解决AOF文件体积不断增大的问题,用户可以向Redis发送BGREWRITEAOF命令,这个命令会通过移除AOF文件中的冗余命令来重写AOF文件,使AOF文件的体积变的尽可能的小。BGREWRITEAOF命令的工作原理和BGSAVE相似,会创建一个子进程,所以也会导致性能和内存占用问题。更糟糕的是,AOF文件按的体积可能会比快照文件按大好几倍,在进行AOF重写和删除的时候,可能会导致系统挂起数秒。

跟快照一样,AOF持久化可以通过设置auto-aof-rewrite-percentage选项和auto-aof-rewrite-min-size来自动执行BGREWRITEAOF。

例如:

1
2
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

那么当AOF文件的体积大于64MB, 并且AOF文件的体积比上一次重写的体积至少大一倍(100%)时,将执行BGREWRITEAOF命令。

不管怎样,将数据持久化到硬盘上都是有必要的,初次之外,用户还必须对持久化所得的文件进行备份,来防止数据 丢失。

主从服务器

对于有扩展平台以适应更高负载经验的工程师和管理员来说,复制(replication)是不可或缺的。复制可以让其他服务器有一个不断更新的数据副本,从而使得拥有数据副本的服务器 可以用于处理客户端发送的读请求。关系数据通常会使用一个主服务器(master)向多个从服务器(slave)发送更新,并使用从服务器处理读请求。Redis也同样采用这种手段。

在需要扩展读请求的手,或者在需要写入临时数据的时候,用户可以通过设置额外的Redis从服务器来保存数据集的副本。在收到住服务器发送的数据初始副本(initial copy of the data)之后,客户端每次向主服务器写入时,从服务器都会实时地得到更新。在部署好主从服务器之后,客户端就可以向任意一个从服务器发送读请求了。

主从配置

由于当从服务器连接上主服务器的时候,主服务器会执行BGSAVE操作。因此为了正确的使用复制特性,用户需要保证主服务器已经争取的配置了上面4-1配置中的dir选项和dbfilename选项,并且两个选项执行的路径和文件对于Redis进程都是可写的。

开启从服务器所必须的选项只有slaveof一个,如果用户在启动Redis服务器的时候,指定了一个包含slaveof host port选项的配置文件,那么Redis服务器将根据该选项给定的IP地址和端口号来连接主服务器。对于一个正在运行的Redis服务器,用户可以通过发送SLAVEOF no one命令来让服务器终止复制操作,不在接受主服务器的数据更新;也可以发送SLAVEOF host port命令来让服务器开始复制一个新的主服务器。

Redis复制的启动过程

​ 表4-2

步骤 主服务器操作 从服务器操作
1 (等待命令进入) 连接(或者重连接)主服务器,发送sync命令
2 开始执行BGSAVE,并使用缓冲区记录BGSAVE之后执行的所有命令 根据配置选项来决定时继续使用现有的数据(如果有的话)来处理客户请求,还是向发送请求的客户端 返回错误
3 BGSAVE执行完毕,向从服务器发送快照文件,并在发送期间继续使用缓冲区记录被执行的写命令 丢弃所有旧数据(如果有),开始载入主服务器发来的快照文件
4 快照发送完毕,开始向从服务器发送存储在缓冲区的写命令 完成对快照的解释 操作,像往常一样开始接受命令请求
5 缓冲区缓存的写命令发送完毕,从现在开始没执行一个写命令,就向从服务器发送相同的写命令 执行主服务器发来的所有存储在缓冲区的写命令,并从现在开始,接收并执行主服务器传来的每个写命令。

主从链

当读请求的重要性明显高于写请求的重要性,并且读请求的数量远远高出一台Redis服务器可以处理的范围,用户就需要添加新的从服务器来处理请求。随着负载不断上升,主服务器可能会无法快速的更新所有从服务器,或者因为重新连接和重新同步从服务器导致系统超载。为了缓解这个问题,用户可以创建一个由Redis主从节点(master/slave node)组成中间层来分担主服务器的复制工作。如下图所示: