一、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