什么是主从复制
- 一个master可以有多个slave
- 一个slave只能有一个master
- 数据流是单向的,master到slave
全量复制和部分复制
run id 查看复制偏移量(用来比对两边数据同步问题,相差不能太大)
- 插一个命令
redis-cli -p 6379 info server | grep run
查看redis运行id
-
查看复制偏移量
全量复制
在Redis复制的基础上,使用和配置主从复制非常简单,它允许从属Redis服务器成为主服务器的精确副本。每次链路断开时,从设备将自动重新连接到主设备,无论主设备发生什么情况,都将试图成为主设备的精确副本。
这个系统使用三个主要机制:
- 当主和从实例连接良好时,主设备通过发送命令流来保持从设备更新,以便复制对主数据集中发生的数据集的影响:客户机写入,密钥过期或被驱逐等等。
- 当主站和从站之间的链路断开时,对于网络问题或者由于在主站或从站中感测到超时,从站重新连接并尝试进行部分重新同步:这意味着它将尝试只获取部分在断开连接时错过的命令流。
- 当部分重新同步不可能时,从机将要求完全重新同步。这将涉及一个更复杂的过程,在这个过程中,主机需要创建所有数据的快照,将数据发送给从机,然后在数据集更改时继续发送命令流。
Redis默认使用异步复制,这是高延迟和高性能,是绝大多数Redis用例的自然复制模式。 但是,Redis从站会异步确认主站定期收到的数据量。
某些数据的同步复制可以由客户端使用WAIT命令来请求。 但WAIT只能确保在其他Redis实例中具有指定数量的已确认副本:在故障转移期间出于不同原因的故障转移期间,确认写入仍可能丢失,或取决于Redis持久性的确切配置。 您可以检查Sentinel或Redis群集文档以获取有关高可用性和故障转移的更多信息。 本文的其余部分主要描述了Redis基本复制的基本特征。
以下是关于Redis复制的一些非常重要的事实:
Redis使用异步复制,异步从到主机确认处理的数据量。
主人可以有多个奴隶。
从站能够接受来自其他从站的连接。除了将多个从站连接到同一个主站之外,从站也可以以层叠状结构连接到其他从站。自从Redis 4.0以来,所有的子从服务器都会收到与主服务器完全相同的复制流。
Redis复制在主端是非阻塞的。这意味着当一个或多个从机执行初始同步或部分重新同步时,主机将继续处理查询。
复制在很大程度上也是非阻塞的。从服务器执行初始同步时,它可以使用旧版本的数据集处理查询,假定您在redis.conf中配置了Redis。否则,如果复制流已关闭,则可以将Redis从属程序配置为向客户端返回错误。但是,在初始同步之后,必须删除旧数据集,并且必须加载新数据集。从站将在这个简短的窗口中阻塞传入的连接(对于非常大的数据集可能只有很多秒)。自Redis 4.0以来,可以配置Redis,以便旧数据集的删除发生在不同的线程中,但是加载新的初始数据集仍然会在主线程中发生并阻止从属。
复制既可用于可伸缩性,也可用于只读查询的多个从站(例如,可将低速O(N)操作卸载到从站),或者仅用于数据安全。
可以使用复制来避免让主服务器将完整数据集写入磁盘的成本:一种典型的技术包括配置主服务器redis.conf以避免永久保存到磁盘,然后连接配置为不时保存的从服务器或启用AOF。然而,这个设置必须小心处理,因为重新启动的主设备将从一个空数据集开始:如果从设备尝试与其同步,则从设备也将被清空。
当master宕机的复制安全
在使用Redis复制的设置中,强烈建议在主服务器和从服务器中启用持久性。如果这种情况不可行,例如由于磁盘速度非常慢导致的延迟问题,则应配置实例以避免重新启动后自动重新启动。
为了更好地理解关闭配置为自动重启的主设备是否危险的原因,请检查以下故障模式,其中数据从主设备及其所有从设备擦除:
- 我们有一个设置,节点A作为主节点,持久性关闭,节点B和C从节点A复制。
- 节点A崩溃,但它有一些自动重新启动系统,重新启动过程。但是由于持久性被关闭,节点将重新启动一个空的数据集。
- 节点B和C将从节点A复制,节点A是空的,所以它们将有效地销毁它们的数据副本。
当Redis Sentinel用于高可用性时,关闭主服务器上的持久性以及进程的自动重启也是危险的。例如,主机可以很快重启,Sentinel不会检测到故障,以便发生上述故障模式。
每次数据安全很重要,复制与配置为无持久性的主站一起使用时,应禁用实例的自动重启。
当Redis Sentinel用于高可用性时,关闭主服务器上的持久性以及进程的自动重启也是危险的。 例如,主机可以很快重启,Sentinel不会检测到故障,以便发生上述故障模式。
每次数据安全很重要,复制与配置为无持久性的主站一起使用时,应禁用实例的自动重启。
Redis复制如何工作
每个Redis master都有一个复制ID:它是一个大的伪随机字符串,标记数据集的给定故事。 每个主设备也会获得一个偏移量,该设置为生成的每个复制流字节增加以发送到从设备,以便使用修改数据集的新更改更新从设备的状态。 即使没有从机连接,复制偏移量也会增加,所以基本上每一对给定的:
识别主数据集的确切版本。
当从站连接到主站时,它们使用PSYNC命令来发送它们的旧主站复制ID以及到目前为止处理的偏移量。这样主人可以发送所需的增量部分。但是,如果主缓冲区中没有足够的积压,或者从服务器引用了不再知道的历史记录(复制标识),则会发生完全重新同步:在这种情况下,从服务器将获得数据集的完整副本, 从头开始。
这是完全同步如何更详细地工作:
主人开始一个后台保存过程,以生成一个RDB文件。同时开始缓冲从客户端收到的所有新的写入命令。当后台保存完成后,主服务器将数据库文件传输给从服务器,将其保存到磁盘上,然后将其加载到内存中。主机会将所有缓冲的命令发送给从机。这是作为命令流完成的,并且与Redis协议本身的格式相同。
你可以通过telnet自己尝试一下。在服务器正在做一些工作的同时连接到Redis端口并发出SYNC命令。您将看到一个批量传输,然后主机接收到的每个命令都将在远程登录会话中重新发出。实际上,SYNC是一个旧的协议,不再由较新的Redis实例使用,但仍然存在向后兼容性:它不允许部分重新同步,所以现在使用PSYNC。
如前所述,当主从链路出于某种原因关闭时,从站能够自动重新连接。如果主站收到多个并发的从站同步请求,它将执行一次后台保存,以便为它们提供全部服务。
无盘复制
通常情况下,完全重新同步需要在磁盘上创建一个RDB文件,然后从磁盘重新加载相同的RDB,以便向从属设备提供数据。
对于较慢的磁盘,对于主设备来说这可能是一个非常紧张的操作。 Redis 2.8.18版是第一个支持无盘复制的版本。 在此设置中,子进程直接通过线将RDB发送到从服务器,而不使用磁盘作为中间存储。
全量复制开销
- bgsave时间
- RDB文件网络传输时间
- 从节点清空数据时间
- 从节点加载RDB时间
- 可能的AOF重写时间
部分复制
连接断开时,master会写一个复制缓冲区的命令,slave再连接master时候会把自己的偏量值offset和runid告诉master,如果丢失数据在buffer缓存的一个范围内,则master把缓冲区队列的数据给slave。然后再把部分数据同步给slave
复制的配置
slaveof命令
- 复制命令
slaveof 127.0.0.1 6380
丢弃旧数据集,转而开始对新主服务器进行同步。
- 取消复制
slaveof no one
将使得这个从属服务器关闭复制功能,并从从属服务器转变回主服务器,原来同步所得的数据集不会被丢弃。
配置
主要修改4个参数:
- port;
- logfile;
- slaveof;
- pidfile;
- daemonize(是否在后台执行)
然后再添加配置
slaveof ip port
slave-read-only yes #设置只读
两种方式比较
方式 | 命令 | 配置 |
---|---|---|
优点 | 无需重启 | 统一配置 |
缺点 | 不便于管理 | 需要重启 |
实战
- 我配置了一个端口为6379,和端口为6380的服务,并在后台启动
#6379配置
port 6379
pidfile /var/run/redis_6379.pid
# slaveof <masterip> <masterport>
logfile "6379.log"
daemonize yes
#6380配置
port 6380
pidfile /var/run/redis_6380.pid
slaveof 127.0.0.1 6379
masterauth xxxxx #如果master有密码,则需要设置
logfile "6380.log"
daemonize yes
-
-
然后我在主机上set一个东西,在slave上获取
同步数据
在master的cli中执行slaveof 127.0.0.1 6380