Redis主从复制
主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(Master/Leader),后者称为从节点(Slave/Follower), 数据的复制是单向的!只能由主节点复制到从节点(主节点以写为主、从节点以读为主)。
默认情况下,每台Redis服务器都是主节点,一个主节点可以有0个或者多个从节点,但每个从节点只能由一个主节点。
作用
- 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余的方式。
- 故障恢复:当主节点故障时,从节点可以暂时替代主节点提供服务,是一种服务冗余的方式
- 负载均衡:在主从复制的基础上,配合读写分离,由主节点进行写操作,从节点进行读操作,分担服务器的负载;尤其是在多读少写的场景下,通过多个从节点分担负载,提高并发量。
- 高可用基石:主从复制还是哨兵和集群能够实施的基础。
环境配置
-
查看当前库的信息 info repliacation
127.0.0.1:6379> info replication # Replication role:master connected_slaves:0 master_failover_state:no-failover master_replid:7d80795751effcf72641bf424258d5dc5429b59d 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
一主二从配置
-
复制redis.conf配置文件,修改对应的信息
[root@hecs-66166 mconfig]# ls redis.conf [root@hecs-66166 mconfig]# cp redis.conf redis6379.conf [root@hecs-66166 mconfig]# cp redis.conf redis6380.conf [root@hecs-66166 mconfig]# cp redis.conf redis6381.conf [root@hecs-66166 mconfig]# ls redis6379.conf redis6380.conf redis6381.conf redis.confxxxxxxxxxx # cp redis.conf redis6379.conf# cp redis.conf
-
依次修改对应的三个配置信息, **:wq!**保存退出
-
端口号
-
pid名字
-
log文件名称
-
rdb文件名称
-
-
分别启动三个redis
- 注意,如果遇到-bash: redis-server: command not found这种错误,只需要将/redis/src/下的redis-server复制移动到/usr/bin/下即可((相当于创建一个全局快捷方式)
[root@hecs-66166 mconfig]# redis-server redis6379.conf [root@hecs-66166 mconfig]# redis-server redis6380.conf [root@hecs-66166 mconfig]# redis-server redis6381.conf [root@hecs-66166 mconfig]# ps -ef |grep redis root 240286 1 0 17:50 ? 00:00:00 redis-server 127.0.0.1:6379 root 240292 1 0 17:50 ? 00:00:00 redis-server 127.0.0.1:6380 root 240298 1 0 17:50 ? 00:00:00 redis-server 127.0.0.1:6381 root 240306 233038 0 17:50 pts/1 00:00:00 grep --color=auto redis
-
分别查看每台redis的信息(默认情况下每一台redis都是主机)
############################6379######################### [root@hecs-66166 bin]# redis-cli -p 6379 127.0.0.1:6379> ping PONG 127.0.0.1:6379> info replication # Replication role:master connected_slaves:0 master_failover_state:no-failover master_replid:bb5fcefe6abb7444d7b032596398279686e12c0d 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 ############################6380######################### [root@hecs-66166 ~]# redis-cli -p 6380 127.0.0.1:6380> ping PONG 127.0.0.1:6380> info replication # Replication role:master connected_slaves:0 master_failover_state:no-failover master_replid:5d418ab0fec977b80fd9c53a281264a1c0d94530 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 ############################6381######################### [root@hecs-66166 ~]# redis-cli -p 6381 127.0.0.1:6381> ping PONG 127.0.0.1:6381> info replication # Replication role:master connected_slaves:0 master_failover_state:no-failover master_replid:3a4e7a6e162b9c6f2fe4831ef4f060561d899ad6 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
-
配置从机(1主(6379)2从 (6380、6381))
- 配置从机
127.0.0.1:6380> SLAVEOF 127.0.0.1 6379 OK 127.0.0.1:6380> info replication # Replication role:slave master_host:127.0.0.1 master_port:6379 master_link_status:down master_last_io_seconds_ago:-1 master_sync_in_progress:0 slave_read_repl_offset:0 slave_repl_offset:0 master_link_down_since_seconds:-1 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:5d418ab0fec977b80fd9c53a281264a1c0d94530 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:6379> info replication # Replication role:master connected_slaves:2 slave0:ip=127.0.0.1,port=6380,state=online,offset=112,lag=1 slave1:ip=127.0.0.1,port=6381,state=online,offset=126,lag=1 master_failover_state:no-failover master_replid:41bd19475f7bb08d322fd8ff78c6f593c74bc127 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:126 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:126
我们这里是使用命令搭建,是暂时的,==真实开发中应该在从机的配置文件中进行配置,==这样的话是永久的。
################################# REPLICATION ################################# # Master-Replica replication. Use replicaof to make a Redis instance a copy of # another Redis server. A few things to understand ASAP about Redis replication. # # +------------------+ +---------------+ # | Master | ---> | Replica | # | (receive writes) | | (exact copy) | # +------------------+ +---------------+ # # 1) Redis replication is asynchronous, but you can configure a master to # stop accepting writes if it appears to be not connected with at least # a given number of replicas. # 2) Redis replicas are able to perform a partial resynchronization with the # master if the replication link is lost for a relatively small amount of # time. You may want to configure the replication backlog size (see the next # sections of this file) with a sensible value depending on your needs. # 3) Replication is automatic and does not need user intervention. After a # network partition replicas automatically try to reconnect to masters # and resynchronize with them. # # replicaof <masterip> <masterport> #配置主机的信息 # If the master is password protected (using the "requirepass" configuration # directive below) it is possible to tell the replica to authenticate before # starting the replication synchronization process, otherwise the master will # refuse the replica request. # # masterauth <master-password> #若有密码验证,配置密码即可
使用规则
-
主机可读可写但是多用于写, 从机只能读,不能写。
#######################测试从机写数据################ 127.0.0.1:6380> keys * (empty array) 127.0.0.1:6380> set k1 v1 (error) READONLY You can't write against a read only replica. #####################测试主机写数据################## 127.0.0.1:6379> keys * (empty array) 127.0.0.1:6379> set k1 v1 OK #####################测试从机读数据################## 127.0.0.1:6380> get k1 "v1"
-
当主机断电宕机后,默认情况下从机的角色不会发生变化 ,集群中只是失去了写操作,当主机恢复以后,又会连接上从机恢复原状。
#####################测试主机宕机################## 127.0.0.1:6379> SHUTDOWN not connected> exit [root@iZ2zedw5vursd09dhzivjnZ bin]# #####################查看从机信息################## 127.0.0.1:6380> info replication # Replication role:slave master_host:127.0.0.1 master_port:6379 master_link_status:down master_last_io_seconds_ago:-1 master_sync_in_progress:0 slave_read_repl_offset:290 slave_repl_offset:290 master_link_down_since_seconds:21 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:41bd19475f7bb08d322fd8ff78c6f593c74bc127 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:290 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:290 ###################重启主机信息#################### [root@hecs-66166 bin]# redis-cli -p 6379 127.0.0.1:6379> ping PONG 127.0.0.1:6379> info replication # Replication role:master connected_slaves:2 slave0:ip=127.0.0.1,port=6380,state=online,offset=360,lag=1 slave1:ip=127.0.0.1,port=6381,state=online,offset=360,lag=0 master_failover_state:no-failover master_replid:b5a15a566fa2df80ef2f9d49b4e2b99e4d45c2ff master_replid2:41bd19475f7bb08d322fd8ff78c6f593c74bc127 master_repl_offset:360 second_repl_offset:291 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:291 repl_backlog_histlen:70
-
当从机断电宕机后,若不是使用配置文件配置的从机,再次启动后默认作为主机是无法获取之前原主机的数据的,若此时重新配置称为从机,又可以获取到主机的所有数据。这里就要提到一个同步原理。
#################测试从机宕机######################## 127.0.0.1:6381> SHUTDOWN not connected> exit #################查看进程########################### [root@hecs-66166 mconfig]# ps -ef |grep redis root 240292 1 0 17:50 ? 00:00:00 redis-server 127.0.0.1:6380 root 240340 240315 0 17:52 pts/2 00:00:00 redis-cli -p 6380 root 240473 1 0 17:59 ? 00:00:00 redis-server 127.0.0.1:6379 root 240518 232062 0 18:00 pts/0 00:00:00 redis-cli -p 6379 root 240535 233038 0 18:01 pts/1 00:00:00 grep --color=auto redis #################查看主机信息########################### 127.0.0.1:6379> info replication # Replication role:master connected_slaves:1 slave0:ip=127.0.0.1,port=6380,state=online,offset=500,lag=1 master_failover_state:no-failover master_replid:b5a15a566fa2df80ef2f9d49b4e2b99e4d45c2ff master_replid2:41bd19475f7bb08d322fd8ff78c6f593c74bc127 master_repl_offset:500 second_repl_offset:291 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:291 repl_backlog_histlen:210 ####################重启从机######################## [root@hecs-66166 bin]# redis-server ./mconfig/redis6381.conf [root@hecs-66166 bin]# redis-cli -p 6381 127.0.0.1:6381> ping PONG 127.0.0.1:6381> info replication # Replication role:master connected_slaves:0 master_failover_state:no-failover master_replid:0c54e4dd76325946d42fb3b5d1df9ba672008566 master_replid2:410d8f04b43af61d9517da4e4d25c217b670e296 master_repl_offset:1690 second_repl_offset:1691 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1691 repl_backlog_histlen:0 ###################测试获取原来主机的数据################ 127.0.0.1:6381> get k1 (nil) ###################################################### 我们会发现这一台已经成为了主机,但获取不了原主机的数据,我们需要再次配置从机信息后才能获取到主机写入的数据 ###################################################### ###################配置从机信息######################## 127.0.0.1:6381> SLAVEOF 127.0.0.1 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:2 master_sync_in_progress:0 slave_read_repl_offset:49626 slave_repl_offset:49626 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:b5a15a566fa2df80ef2f9d49b4e2b99e4d45c2ff master_replid2:0000000000000000000000000000000000000000 master_repl_offset:49626 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:49627 repl_backlog_histlen:0 127.0.0.1:6381> get k1 "v1"
-
第二条中提到,默认情况下,主机故障后,不会出现新的主机,有两种方式可以产生新的主机:
-
从机手动执行命令
slaveof no one
,这样执行以后从机会独立出来成为一个主机,其他的节点就可以手动连接到最新的主节点(手动)127.0.0.1:6381> SLAVEOF no one OK 127.0.0.1:6381> INFO REPLICATION # Replication role:master connected_slaves:0 master_failover_state:no-failover master_replid:fcc781049a15be144093e78741548b99da093a69 master_replid2:b5a15a566fa2df80ef2f9d49b4e2b99e4d45c2ff master_repl_offset:50592 second_repl_offset:50593 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:49627 repl_backlog_histlen:966 #####如果后续主机恢复了,那么就相当于光杆司令了,只能再重新配置主从复制######
-
使用哨兵模式(自动选举),下一篇文章会介绍到
-
复制原理
- Slave命令启动成功连接到Master主机后会发送psync命令(Redis2.8之前版本是sync命令),开始进行数据同步
- Master主机接收到psync命令,启动后台的存盘进程,同时收集所有接收到的写的命令,在后台进程执行完毕之后,Mater会将整个数据文件传送到Slave,并完成一次完全同步
- 全量复制:Slave服务在接收到数据库文件数据后,将其存盘并加载到内存中
- 增量复制:Master服务继续将修改的命令一次传送到Slave服务,完成同步
- 但是只要重新连接Master,一次完全同步(全量复制)将自动执行!我们的数据一定可以在从机中看到
层层链路
上一个Master主机链接下一个Slave从机
也就是6379是主机,6380既是主机也是从机 ,6381是6380的从机
我们在获取数据的时候,6380显示的信息依旧是6379的从机,它能读6379的数据,6381也能读6379的数据
#################################测试6379主机##################################
[root@hecs-66166 ~]# redis-cli -p 6379
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6380,state=online,offset=28,lag=0
master_failover_state:no-failover
master_replid:1893a9622491d130a17c0afb55e26829d2b89137
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> keys *
(empty array)
127.0.0.1:6379> set k1 v1
OK
#################################测试6380主机从机##################################
[root@hecs-66166 ~]# redis-cli -p 6380
127.0.0.1:6380> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:7
master_sync_in_progress:0
slave_read_repl_offset:280
slave_repl_offset:280
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:1
slave0:ip=127.0.0.1,port=6381,state=online,offset=280,lag=0
master_failover_state:no-failover
master_replid:1893a9622491d130a17c0afb55e26829d2b89137
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:280
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:280
127.0.0.1:6380> get k1
"v1"
#################################测试6381从机##################################
127.0.0.1:6381> SLAVEOF 127.0.0.1 6380
OK
127.0.0.1:6381> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6380
master_link_status:down
master_last_io_seconds_ago:-1
master_sync_in_progress:0
slave_read_repl_offset:50592
slave_repl_offset:50592
master_link_down_since_seconds:-1
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:fea79ddb9f0b1da3c2b64e96b224fbec8689e28f
master_replid2:fcc781049a15be144093e78741548b99da093a69
master_repl_offset:50592
second_repl_offset:50593
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:50593
repl_backlog_histlen:0
127.0.0.1:6381> get k1
"v1"