Redis还提供了主从复制的机制,实现Redis从机服务器精确地复制Redis主机服务器上的数据。每次连接中断后,从机会自动地与主机再次建立连接,并尝试与主机同步成为主机的副本。
1.实现机制
Redis主从复制系统的实现主要依赖于以下三个机制:
(1)连接时
当主机和从机处于连接状态时,主机会通过发送命令流(stream of commands)的方式来保持从机的更新,这些命令流主要是为了将在主机数据集上产生的变化复制到从机上,这些变化有:客户端的写操作、key过期或被删除等等。
(2)断连时
当主机和从机处于断连状态时,从机会尝试重新连接并试图进行部分再同步(partial resynchronization)操作:这意味着从机将尝试获取在断连期间错过的那部分命令流。
(3)部分同步失效时
如果无法获取断连期间丢失的那部分命令流的话,从机将会向主机请求一次完全同步(full resynchronization)更新操作。这是一个相对复杂的过程:主机首先要创建它所有数据的快照,并发送给从机,然后再将快照之后产生的数据集修改以命令流的方式发送给从机。
Redis使用默认的异步复制模式,这是一种高延迟、高性能的复制模式,也是大多数Redis用例使用的一般复制模式。并且,Redis从机会异步的向主机确认接收到的数据量。
客户端可以通过WAIT命令实现对某些数据的同步复制。
以下几点是关于Redis主从复制的一些重要说明:
(1)Redis使用异步复制机制,并对处理的数据数量进行从机到主机(slave-to-master)的异步确认。
(2)一个主机可以拥有多个从机。
(3)从机能够接受来自其他从机的连接。我们已经知道多个从机可以连接到一个主机了,除此之外,从机也是可以连接到其他从机的。从Redis4.0之后,所有的子从机(sub-slaves)将会从主机接收到完全相同的复制流。
(4)Redis主从复制在主机一端是非阻塞的。这意味着,当一个或多个从机执行初始化全同步或部分同步时,不会影响到主机的其他业务(比如,继续处理查询等操作)。
(5)Redis主从复制在从机一端基本上也是非阻塞的。假设你已经在redis.conf做了配置,当从机在执行初始化同步时,它可以使用旧版的数据集来处理查询。但是,在初始同步之后,必须将旧版的数据集删除,并加载新的数据集。在这个短暂的过程中(如果数据集很大的话可能会长达数秒),从机将会阻塞其他从机的连接请求。
(6)主从复制同样具有良好的伸缩性,比如让多个从机用于较为耗时的只读查询或仅仅是出于数据安全性的考虑。
(7)使用主从复制可以降低主机将所有数据集写入磁盘的成本:一个典型的技术是配置主机的redis.conf文件以避免将数据持久化到磁盘。但是,该操作需要小心使用:因为重新启动主机服务器时将会以一个空数据集开始,如果从机试图与它同步,那么从机也将被清空。
2.安全性讨论
主机关闭数据持久化功能,会给主从机带来一定的安全隐患。
通常,Redis建议在主机和从机中都开启数据持久化功能。如果不开启持久化功能,那么你也至少要保证在操作系统重启后,避免主从机的Redis实例自动重新启动。
如下示例可以更好的帮助我们理解这种危险性:
(1)首先,我们有一台关闭持久化功能的主机A,两台从机B和C。B,C会从A上复制数据;
(2)某刻,主机A崩溃,主机A的Redis实例也自动重启。由于A未开启持久化功能,导致重启后Redis实例的数据集为空。
(3)此时,B和C对A进行主从复制,最终导致B和C的有效数据也全部丢失。
所以,关闭持久化功能并将Redis实例配置为自动启动的场景不应该出现。毕竟,数据无价。
3.工作机制
主从复制机制中,每个Redis主机都有一个复制ID(Replication ID)和一个偏移量(offset)。该偏移量会在主机发送给从机的复制流上进行递增偏移,用来对从机更新主机数据集上产生的新修改。
当从机连接到主机之后,从机会通过PSYNC命令发送从机目前所处的状态,如复制ID和偏移量。这样一来,主机就可以根据复制ID和偏移量只发送从机所需的增量部分。然而,如果从机的复制ID已经不为人知了,它们将会进行完全同步操作:从机将从头获取数据集的完整副本。
接下来,让我们来深入完全同步(full synchronization)机制的流程及细节:
(1)首先,主机在后台开启一个进程,用来生成RDB文件。
(2)与此同时,主机会缓存下所有源自客户端的写命令(读命令不会影响到数据集的已有数据)。
(3)当主机后台的保存进程完成RDB文件的生成之后,主机会将此数据库文件传输给从机。
(4)从机接收到该文件之后,先保存到磁盘上,再从磁盘加载到内存中。
(5)最后,主机将前面缓存下来的写命令以命令流的方式发送给从机,从机更新到最新状态。
至此,一个完整的完全同步就完成了。
4.无盘复制
如上所述,完全同步机制先将生成的RDB文件存储在磁盘上,然后发送给从机,从机再存盘,最后加载。
然而,对于速度慢的磁盘来说,这无疑将会影响到Redis的性能。Redis2.8.18版本提供了无盘复制的特性,通过配置之后,主机的子进程通过socket连接,直接将RDB文件发送给从机,而不再使用磁盘作为中间存储介质。
5.配置
(1)主从设置
Redis主从复制的配置特别简单,有两种方法:一种是通过修改配置文件redis.conf,在配置文件中加入格式如下的条目:
1 |
slaveof <masterip> <masterport> |
比如,salveof <192.168.10.12> 6379,其中192.168.10.12和6379是主机ip和端口。
另一种设置方法,则是使用SLAVEOF命令。
(2)backlog设置
我们知道,从机和主机断连期间,主机做的修改会在从机再次和主机建连之后由部分再同步(partial resynchronization)功能实现主从机的同步。
然而,主从机断连时间的长短也是有限定的,这个时间有一个重要的影响因素——backlog。什么是backlog?Redis给出的解释是:The backlog is a buffer that accumulates slave data when slaves are disconnected for some time。即:backlog是一个缓冲区,该缓冲区会在断连期间用来存储数据。
所以,如果在backlog缓冲区存满之后主从机仍然没有建连,那么,Redis将无法使用部分再同步特性。
由此可知,在Redis能够正常使用“部分再同步”特性的前提下,backlog 缓冲区的大小将影响到允许主从机断连时间的长短:backlog缓冲区越大,允许主从机断连的时间相对就越久,backlog缓冲区越小,允许主从机断连的时间就越短。
Redis配置文件中,backlog的大小默认为1M,当然你也可以修改为其他值,如下所示:
1 |
repl-backlog-size 1mb |
(3)无盘复制
在Redis配置文件redis.conf中,通过如下条目开启Redis无盘复制特性:
1 |
repl-diskless-sync no |
其他配置条目可参考redis.conf。
6.示例
由于是单机操作,所以我们需要在一台机器上开启两个Redis服务,分别用来充当主机和从机的Redis实例(如果你有两台机器就无需这样做了)。
(1)redis-server
首先我们需要知道,当启动redis-server时,实际上该服务使用了默认的配置文件redis.conf,并且在该配置文件中指定了默认监听端口为6379。所以,我们需要拷贝一份这个配置文件,并将其中的默认端口修改为其他值,比如port 6666。
此时我们就有了两个Redis配置文件,也就具备了启动两个Redis服务的能力:
1 2 3 4 |
#使用Redis默认配置文件,默认监听端口为6379 [root@localhost src]# redis-server #使用指定的配置文件,其中指定监听端口为6666 [root@localhost src]# redis-server /home/redis.conf_bak |
(2)redis-cli
启动两个Redis客户端,分别连接6379和6666的Redis服务:
1 2 3 4 5 6 |
#启动连接6379的客户端 [root@localhost src]# redis-cli 127.0.0.1:6379> #启动连接6666的客户端 [root@localhost src]# redis-cli -p 6666 127.0.0.1:6666> |
(3)slaveof
前面介绍过,建立主从关系有两种方法:配置文件或命令行。此处使用命令slaveof,将6666设置为6379的从机:
1 2 |
127.0.0.1:6666> SLAVEOF 127.0.0.1 6379 OK |
(4)主机修改
主机设置一个counter,初始值为1,随后自增,此时counter的值为2:
1 2 3 4 |
127.0.0.1:6379> SET counter 1 OK 127.0.0.1:6379> INCR counter (integer) 2 |
(5)从机同步
从机获取counter:
1 2 |
127.0.0.1:6666> GET counter "2" |
OK,主-从复制得以实现。若想解除主从复制关系,使用命令:
1 2 |
127.0.0.1:6666> SLAVEOF no one OK |
7.其他
本文主要介绍了Redis主从复制的一般使用方法和部分特性,其他未提及的内容可参考文末的参考链接。
参考:
https://redis.io/topics/replication