概念
主从复制,是指将一台 Redis 服务器的数据,复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave);数据的复制是单向的,只能由主节点到从节点。
默认情况下,每台Redis服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。
主从复制的作用
主从复制的作用主要包括:
- 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
- 故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
- 负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
- 高可用基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。
如何使用主从复制
为了更直观的理解主从复制,在介绍其内部原理之前,先说明我们需要如何操作才能开启主从复制。
1. 建立复制
需要注意,主从复制的开启,完全是在从节点发起的;不需要我们在主节点做任何事情。
从节点开启主从复制,有 3 种方式:
(1)配置文件
在从服务器的配置文件中加入:slaveof
(2)启动命令
redis-server启动命令后加入 --slaveof
(3)客户端命令
Redis服务器启动后,直接通过客户端执行命令:slaveof ,则该Redis实例成为从节点。
上述 3 种方式是等效的,下面以客户端命令的方式为例,看一下当执行了slaveof 后,Redis 主节点和从节点的变化。
2. 实例
准备工作:启动两个节点
-
复制配置文件
[root@localhost bin]# ls ### 进入redis 安装目录下可执行目录
dump.rdb redis-benchmark redis-check-aof redis-check-rdb redis-cli redis.conf redis-sentinel redis-server
[root@localhost bin]# cp redis.conf redis1.conf ### 复制配置文件作为其中一个从机
[root@localhost bin]# cp redis.conf redis2.conf ### 复制配置文件作为其中一个从机
[root@localhost bin]# vi redis1.conf ### 修改redis1.conf端口为 6381
##***** :/6379 搜索即可找到
此时之前的 redis 实例端口为6379 ,现在又多一个6381。
接下来分别启动各自服务。
启动6379:
[root@localhost bin]# redis-server redis.conf ###******* 注意使用各自的配置文件
16624:C 05 Aug 2021 09:11:14.767 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
16624:C 05 Aug 2021 09:11:14.767 # Redis version=6.0.6, bits=64, commit=00000000, modified=0, pid=16624, just started
16624:C 05 Aug 2021 09:11:14.767 # Configuration loaded
[root@localhost bin]# redis-cli -p 6379
127.0.0.1:6379> info replication ###******* 查看主从情况
# Replication
role:master ###******* 默认自己都为master 主节点
connected_slaves:0
master_replid:e2995fc02165a6f45644b6076aa4ae7c75ccf3d6
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:28
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:28
127.0.0.1:6379>
再启动6381:
[root@localhost bin]# redis-server redis1.conf #***** 使用第二个实例配置文件启动
16641:C 05 Aug 2021 09:12:07.514 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
16641:C 05 Aug 2021 09:12:07.515 # Redis version=6.0.6, bits=64, commit=00000000, modified=0, pid=16641, just started
16641:C 05 Aug 2021 09:12:07.515 # Configuration loaded
[root@localhost bin]# redis-cli -p 6381 ##**** 使用6381
127.0.0.1:6381> info replication
# Replication
role:master ##**** 一样显示主节点
connected_slaves:0
master_replid:fdc1b15ab0d76bca91227af2c0ebf8198a7c8541
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:6381>
从上面看出,两个Redis节点启动后(分别称为6379节点和6381节点),默认都是主节点。
3. 主从配置
此时在6381节点执行 slaveof 命令,使之变为从节点:
127.0.0.1:6381> slaveof 127.0.0.1 6379 ## 建立主从关系,附属6379
OK
127.0.0.1:6381> info replication
# Replication
role:slave ## 显示变为了从节点了
master_host:127.0.0.1
master_port:6379
master_link_status:up ## 和主节点保持了连接状态
master_last_io_seconds_ago:0
master_sync_in_progress:0
slave_repl_offset:70
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:e2995fc02165a6f45644b6076aa4ae7c75ccf3d6
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:70
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:29
repl_backlog_histlen:42
127.0.0.1:6381>
再看 6379 节点:
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:1 # 所属从节点有一个
slave0:ip=127.0.0.1,port=6381,state=online,offset=196,lag=1
master_replid:e2995fc02165a6f45644b6076aa4ae7c75ccf3d6
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:196
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:196
测试读写操作:
先在从节点查询一个不存在的 key,然后去主节点添加此 key ,会发现会自动同步到各个从节点
127.0.0.1:6381> get age
(nil)
127.0.0.1:6381> get age ### 当主节点存入age 后 ,再取值,发现已经自动同步到从机了
"23"
127.0.0.1:6381> set age 24
(error) READONLY You can't write against a read only replica.
127.0.0.1:6381>
注意:上面的error提示中,说明从节点是只能读,不能写的。所谓主从复制。读写分离
4. 启动命令方式
redis-server启动命令后加入 --slaveof
上面的方式,使用客户端命令方式来实现的主从的配置。
下面使用启动时指定主从关系。
redis-server myredis/redis1.conf --slaveof 127.0.0.1 6379 启动 Redis 服务时,指定所属的主节点为 6379 端口上的服务
[root@wang ~]# redis-server myredis/redis1.conf --slaveof 127.0.0.1 6379
29087:C 25 Aug 2021 16:04:29.836 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
29087:C 25 Aug 2021 16:04:29.836 # Redis version=6.0.6, bits=64, commit=00000000, modified=0, pid=29087, just started
29087:C 25 Aug 2021 16:04:29.836 # Configuration loaded
[root@wang ~]# redis-cli -p 6381
127.0.0.1:6381> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:2
master_sync_in_progress:0
slave_repl_offset:1007
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:f05b6c77978f163ae77ebed3dcd0bb85790ed197
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:1007
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
5. 配置文件方式
可以在启动的配置文件中 redis1.config 中追加下面的一行配置 :
slaveof 127.0.0.1 6379
[root@wang myredis]# echo "slaveof 127.0.0.1 6379" >> redis1.conf
[root@wang myredis]# tail -5 redis1.conf