Redis主从复制介绍与实战

一、Redis主从复制介绍


Redis主从复制的特点

  • Redis 使用异步复制。

    从 Redis2.8开始,slave会以每秒一次的频率向master报告复制流(replication stream)的处理进度。

  • 一个master可以有多个slave。

  • 除了master可以有slave,slave也可以有自己的slave,多个slave之间可以构成一个图状结构。(级联复制)

  • 复制功能不会阻塞master:即使有一个或多个slave正在进行初次同步, master也可以继续处理命令请求。

  • 复制功能也不会阻塞slave:只要在 redis.conf 文件中进行了相应的设置, 即使slave正在进行初次同步, 服务器也可以使用旧版本的数据集来处理命令查询。

  • 在slave删除旧版本数据集并载入新版本数据集的那段时间内,连接请求会被阻塞。

  • 还可以配置slave,让它在与master之间的连接断开时,向客户端发送一个错误。

  • 复制功能可以单纯地用于数据冗余(data redundancy),也可以通过让多个slave处理只读命令请求来提升扩展性(scalability): 比如说,繁重的SORT命令可以交给附属节点去运行。

  • 可以通过复制功能来让主服务器免于执行持久化操作:只要关闭主服务器的持久化功能,然后由从服务器去执行持久化操作即可。(通常不建议这么做)


Redis主从复制的原理

  • 从库向主库发送 SYNC 命令。

  • 主库接到 SYNC 命令后会调用BGSAVE 命令,创建一个 RDB 文件,并使用缓冲区记录接下来执行的所有写命令。

  • 当主库执行完 BGSAVE 命令时,它会向从库发送 RDB 文件,而从库则会接收并载入这个文件(载入RDB文件前会先清空自己的数据)。

  • 主库将缓冲区储存的所有写命令发送给从库执行。


Redis主从复制工作机制

  • PSYNC只会将从服务器断线期间缺失的数据发送给从服务器,但SYNC需要发送包含整个数据库的RDB文件以及缓冲区的命名。

  • 如果主从服务器所处的网络环境并不那么好的话(经常断线),那么请尽量使用 Redis 2.8 或以上版本:通过使用 PSYNC 而不是 SYNC 来处理断线重连接,可以避免因为重复创建和传输 RDB文件而浪费大量的网络资源、计算资源和内存资源。

注意:

在 Redis2.8版本之前,断线之后重连的从服务器总要执行一次完整重同步(fullresynchronization)操作。

从2.8开始,Redis使用PSYNC命令代替SYNC命令。

PSYNC比起SYNC的最大改进在于PSYNC实现了部分重同步(partial resync)特性:
在主从服务器断线并且重新连接的时候,只要条件允许,PSYNC可以让主服务器只向从服务器同步断线期间缺失的数据,而不用重新向从服务器同步整个数据库。

二、Redis主从复制搭建

部署环境

主机名 IP 角色
redis01 172.16.1.56 master
redis02 172.16.1.57 slave
redis03 172.16.1.58 slave

开启主从复制

在从库上执行SLAVEOF命令,指定主库的IP、端口

  • 在redis02和redis03上执行SLAVEOF命令,指定redis01为主库

执行命令前,检查redils02、redis03状态,确保他们为非从库状态

172.16.1.57:6379> info replication
# Replication
role:master         #当前状态为master状态
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:6379> 

执行SLAVEOF命令

127.0.0.1:6379> slaveof 172.16.1.56 6379
OK
  • 查看主从信息

查看主库(redis01)的主从状态

127.0.0.1:6379> info replication
# Replication
role:master             #角色为主库
connected_slaves:2      #有2个从库
slave0:ip=172.16.1.57,port=6379,state=online,offset=8191,lag=0  
slave1:ip=172.16.1.58,port=6379,state=online,offset=8191,lag=0
master_repl_offset:8191
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:8190

查看从库(redis02)的主从状态

127.0.0.1:6379> info replication
# Replication
role:slave                  #角色是从库
master_host:172.16.1.56     #主库的IP是172.16.1.56
master_port:6379
master_link_status:up
master_last_io_seconds_ago:2
master_sync_in_progress:0
slave_repl_offset:8471
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_acklog_histlen:0

注意:如果redis配置了密码,则需要认证config set masterauth 123

三、主从切换(模拟主库故障)

在当前的环境中,redis01为主库,redis02、redis03为从库。

现在由于主库发生故障,需要把redis02作为主库,redis03仍为从库。

  • 关闭主库(redis01)
[root@redis01 ~]# redis-cli shutdown

查看从库(redis02)的主从状态

127.0.0.1:6379> info replication
# Replication
role:slave
master_host:172.16.1.56
master_port:6379
master_link_status:down         #连接主库的状态是:down
master_last_io_seconds_ago:-1
master_sync_in_progress:0
slave_repl_offset:1
master_link_down_since_seconds:1594204815
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
  • 把从库(redis02)提升为主库

取消redis02的主从关系

127.0.0.1:6379> slaveof no one
OK

查看redis02的从库状态,发现redis02

127.0.0.1:6379> info replication
# Replication
role:master             #此时redis02的角色就成为了master
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

把从库(redis03)的主库指向为redis02

#先取消redis03的主从关系
127.0.0.1:6379> slaveof no one
OK
#指向主为redis02
127.0.0.1:6379> slaveof 172.16.1.57 6379
OK
#查看redis03的主从信息
127.0.0.1:6379> info replication
# Replication
role:slave      
master_host:172.16.1.57     #主库的IP是172.16.1.56
master_port:6379
master_link_status:up       #连接状态是:up
master_last_io_seconds_ago:9
master_sync_in_progress:0
slave_repl_offset:15
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

查看主库(redis02)的主从状态信息,发现redis03已经为它的从库了

127.0.0.1:6379> info replication
# Replication
role:master             #状态为主库
connected_slaves:1      #有1个从库
slave0:ip=172.16.1.58,port=6379,state=online,offset=449,lag=1
master_repl_offset:463
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:462
点赞

发表回复