Redis中可以将一台服务器设置主机,别的服务器设置成从机,实现主从模式
。在Redis的主从模式下主服务器只能写数据
,从服务器只能读数据
。Redis的主从模式会将主服务器中的所有数据会通过写时复制
技术备份到从服务器中,从而保证主从服务器之间的“数据一致性”。
关键词: 主机:master - 写数据 从机:slaver - 读数据
将一台服务器设置为从服务器的命令为:
localhost:6380>slaveof master_ip port # 例如:slaveof localhost 6379 即可将6380端口这台服务器设置为6379端口服务器的从服务器
使用info replication
命令可以查看当前服务器的状态
接着查看主服务器的状态
Redis中搭建主从模式的命令非常简单,下面就来看主从复制原理和服务器宕机时保存数据的解决方案。
下面是Redis中主从复制原理的实现,在不同版本的其实现有些区别。
Redis中的复制功能可以分为两个操作
同步
:将从服务器的数据库状态更新至主服务器的数据库状态。
命令传播
:主服务器的数据被修改之后,将修改命令发送到从服务器中修改对应的数据,保持数据一致性。
当客户端向从服务器发送slaveof命令要求从服务复制主服务器当中的数据时,从服务器会向主服务器发送sync命令
来执行同步操作,会经过如下步骤:
从服务器向主服务器发送sync命令。
主服务器接收到sync命令之后执行bgsave命令
,生成一个rdb文件。同时使用一个缓冲区记录从现在开始执行的所有写命令,这是为了在执行bgsave命令阶段和发送rdb文件阶段主服务器可能有数据被修改了,这一部分修改的数据会在后面通过命令传播的方式复制到从服务器中。
当主服务器执行完bgsave命令之后,会将rdb文件发送给从服务器,从服务器根据这个rdb文件与主服务的数据库状态进行同步。(写时复制技术)
在同步操作实现之后,每当主服务器的数据被修改了,就会通过命令传播的方式向从服务器发送同样的命令修改从服务器中数据,再一次的达到数据同步的效果。
2.8版本以下复制操作的缺陷
在2.8版本以下的复制操作中如果从服务器和主服务器断开连接了(注意不是宕机),再重新连接之后,从服务器会重新执行一遍同步操作,即还是重新发送sync命令
。这种断线后重新复制的操作的效率是非常低下的。例如
在还没有断开连接之前,主从服务器都有键key1,key2,key3...key1000。 在从服务器断开连接到重新恢复连接阶段,主服务器又新加了键key1001,key1002,key1003, 而从服务器仍然之后前面的1000个键。如果这个时候因为这新加的三个键而重新完整的一份rdb数据, 是非常消耗性能和带宽的。
2.8及之上版本就对断开连接之后重新连接的复制进行了优化。
2.8及之上的版本使用psync命令来替代sync命令执行复制时的同步操作。psync命令分为完整重同步和部分重同步两种模式。
部分重同步模式
来实现。部分重同步模式功能的实现有三个部分构成**,偏移量**,复制积压缓冲区,服务器的运行ID。
偏移量 replication offset,主从服务器双方会维护一个复制偏移量,每次主服务器向从服务器传播N个字节的数据的时候就会在自己的偏移量上加上N。同时从服务器在接收到这N个字节之后也会在自己的偏移量上加上N。
通过对比主从服务器的偏移量大小,就很容易能够得出主从服务的数据是否一致。
从服务器向主服务器发送psync信号时会携带自己的偏移量过去。
复制积压缓冲区,是由主服务维护的一个固定长度的队列,默认大小为1MB。当主服务进行命令传播时,不仅会将命令发送给从服务器,还会将命令保存进复制积压缓冲区中。因此队列中会保存最近的命令,同时在队列中会记录对应命令的偏移量。
当主服务器接收到从服务器的psync命令中的偏移量之后,判断从服务器的偏移量和自己当前的偏移量,如果不一致,就去复制积压缓冲区找找对应的偏移量对应的命令发送给从服务器执行。如果偏移量在复制积压缓冲区没有对应,则会进行一次完整重同步操作。
复制积压缓冲区的大小可以去:repl-backlog-size中修改。
服务器运行ID(run ID),每个Redis服务器都有一个属于自己的40位随机的十六进制组成的ID编号。
当从服务器第一次与主服务进行同步时,会保存主服务器的id。接着在断线重连之后会发送主服务器的ID,然后主服务器判断该ID是否与自己的ID相等。如果相等则进行部分重同步的操作,如果不相等,则进行完整重同步操作。
psync命令的格式
psync ? -1
表示第一次复制,此时进行的是完整重同步。
psync <runid> <offset>
完整的主从复制流程图如下:
如果一个从服务器挂掉了,重启之后还是作为一个独立的主服务器,而不会继续作为原来主机的从服务器。需要使用slaveof ip port
命令重新设置。
如果是主服务器挂掉了,从服务器任然是从服务器,主服务器重启之后任然是主服务器。
常用
类似于树的递归方式进行主从服务器的设置。当有一台从服务器断开了,可能会导致树的断开。
当主服务器挂掉了之后,其从服务器中有一台成为主服务器。使用命令:
slaveof no one
这种方式需要手动的进行设置。
检查网络连接状态
在命令传播阶段,从服务器每秒会向主服务发送一次
replconf ack <replication_offset>
这个命令可以起到:
检测主从服务器之间的网络连接状态
在从主务器中通过replication info可以查看如下信息:
lag
就是发送命令的时间差,一般在0-1之间,如果超过1,主从之间的连接可能就断开了。
辅助实现min-slaves选项
redis.conf中有如下两个文件可以避免主服务在不安全的情况下进行写操作:
min-slaves-to-write 3 min-slaves-max-lag 10
在从服务器数量少于3个,或者三个从服务器的延迟都大于10秒时,不进行写操作。
防止命令丢失
在命令传播过程中可能会导致命令丢失,这个使用通过比较发送的replication_offset就可以发现,不一致的情况下主服务器就会从复制积压缓冲区中再发送一次。