主从复制的特点
- 一个master可以有多个slave
- 一个slave只能有一个master
- 数据流向是从master到slave单向的
Redis Slave 也要开启持久化并设置和master同样的连接密码,因为后期slave会有提升为master的可能,Slave端切换master同步后会丢失之前的所有数据,而通过持久化可以恢复数据
一旦某个Slave成为一个master的slave,Redis Slave服务会清空当前redis服务器上的所有数据并将master的数据导入到自己的内存,但是如果只是断开同步关系后,则不会删除当前已经同步过的数据。
当配置Redis复制功能时,强烈建议打开主服务器的持久化功能。否则的话,由于延迟等问题,部署的主节点Redis服务应该要避免自动启动。
1.1 启用主从同步默认redis 状态为master,需要转换为slave角色并指向master服务器的IP+PORT+Password
在从节点执行 REPLICAOF MASTER_IP PORT 指令可以启用主从同步复制功能,早期版本使用SLAVEOF指令
127.0.0.1:6379> REPLICAOF MASTER_IP PORT 127.0.0.1:6379> CONFIG SET masterauth
环境准备
三台机器:
10.0.0.7 Redis-6.2.4 master
10.0.0.17 Redis-6.2.4 slave 1
10.0.0.27 Redis-6.2.4 slave 2
#在mater上设置key1 [root@centos7 ~]#redis-cli 127.0.0.1:6379> AUTH 123456 OK 127.0.0.1:6379> INFO replication # Replication role:master connected_slaves:0 master_failover_state:no-failover master_replid:69647aaf4b664798db3b7bde649674fad6e320af 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> SET key1 v1-master OK 127.0.0.1:6379> KEYS * 1) "key1" 127.0.0.1:6379> GET key1 "v1-master" #在master上可以看到所有slave信息 127.0.0.1:6379> INFO replication # Replication role:master connected_slaves:2 slave0:ip=10.0.0.27,port=6379,state=online,offset=6529,lag=0 #slave信息 slave1:ip=10.0.0.17,port=6379,state=online,offset=6529,lag=1 master_failover_state:no-failover master_replid:3ecc9b36d6175a927c0c46bc5681ca340b4f49d0 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:6529 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:6529 #查看连接状态 [root@centos7 ~]#ss -nt State Recv-Q Send-Q Local Address:Port Peer Address:Port ESTAB 0 0 10.0.0.7:6379 10.0.0.17:45026 ESTAB 0 52 10.0.0.7:22 10.0.0.1:51959 ESTAB 0 0 10.0.0.7:6379 10.0.0.27:44892 #查看Master日志 [root@centos7 ~]#tail -f /apps/redis/log/redis-6379.log 1293:M 04 May 2022 11:25:37.272 * Replica 10.0.0.27:6379 asks for synchronization 1293:M 04 May 2022 11:25:37.273 * Partial resynchronization request from 10.0.0.27:6379 accepted. Sending 3738 bytes of backlog starting from offset 1490. 1293:M 04 May 2022 11:27:35.089 * 1 changes in 3600 seconds. Saving... 1293:M 04 May 2022 11:27:35.090 * Background saving started by pid 2488 2488:C 04 May 2022 11:27:35.141 * DB saved on disk 2488:C 04 May 2022 11:27:35.142 * RDB: 0 MB of memory used by copy-on-write 1293:M 04 May 2022 11:27:35.193 * Background saving terminated with success 1293:M 04 May 2022 11:29:16.729 # Connection with replica 10.0.0.17:6379 lost. 1293:M 04 May 2022 11:29:16.841 * Replica 10.0.0.17:6379 asks for synchronization 1293:M 04 May 2022 11:29:16.841 * Partial resynchronization request from 10.0.0.17:6379 accepted. Sending 4032 bytes of backlog starting from offset 1490.1.3 slave 1
[root@centos7 ~]#redis-cli 127.0.0.1:6379> AUTH 123456 OK 127.0.0.1:6379> INFO replication #查看当前角色默认为master # Replication role:master connected_slaves:0 master_failover_state:no-failover master_replid:2c539210cad9f2660ca76c7ca35a4c41a2aef84e 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 #在slave上设置master的IP和端口 127.0.0.1:6379> REPLICAOF 10.0.0.7 6379 OK #在slave上设置master的密码,才可以同步 127.0.0.1:6379> CONFIG SET masterauth 123456 OK 127.0.0.1:6379> INFO replication # Replication role:slave #角色变为slave master_host:10.0.0.7 #指向master master_port:6379 master_link_status:up master_last_io_seconds_ago:5 master_sync_in_progress:0 slave_repl_offset:98 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:3ecc9b36d6175a927c0c46bc5681ca340b4f49d0 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:98 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:98 #在slave1上查看已经同步成功 127.0.0.1:6379> KEYS * 1) "key1" 127.0.0.1:6379> GET key1 "v1-master" #修改slave节点配置文件 [root@centos7 ~]#vim /apps/redis/etc/redis.conf # replicaof1.4 slave 2replicaof 10.0.0.7 6379 #指定master的IP和端口号 # masterauth masterauth 123456 #指定master的密码 #重启redis服务 [root@centos7 ~]#systemctl restart redis.service #再次登录查看连接状态 [root@centos7 ~]#redis-cli 127.0.0.1:6379> AUTH 123456 OK 127.0.0.1:6379> INFO replication # Replication role:slave master_host:10.0.0.7 master_port:6379 master_link_status:up master_last_io_seconds_ago:11 master_sync_in_progress:0 slave_repl_offset:5745 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:3ecc9b36d6175a927c0c46bc5681ca340b4f49d0 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:5745 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1490 repl_backlog_histlen:4256 #查看slave日志 [root@centos7 ~]#tail -f /apps/redis/log/redis-6379.log 2517:S 04 May 2022 11:29:16.828 * DB loaded from disk: 0.001 seconds 2517:S 04 May 2022 11:29:16.829 * Before turning into a replica, using my own master parameters to synthesize a cached master: I may be able to synchronize with the new master with just a partial transfer. 2517:S 04 May 2022 11:29:16.829 * Ready to accept connections 2517:S 04 May 2022 11:29:16.829 * Connecting to MASTER 10.0.0.7:6379 2517:S 04 May 2022 11:29:16.833 * MASTER <-> REPLICA sync started 2517:S 04 May 2022 11:29:16.834 * Non blocking connect for SYNC fired the event. 2517:S 04 May 2022 11:29:16.836 * Master replied to PING, replication can continue... 2517:S 04 May 2022 11:29:16.838 * Trying a partial resynchronization (request 3ecc9b36d6175a927c0c46bc5681ca340b4f49d0:1490). 2517:S 04 May 2022 11:29:16.840 * Successful partial resynchronization with master. 2517:S 04 May 2022 11:29:16.840 * MASTER <-> REPLICA sync: Master accepted a Partial Resynchronization. #slave状态只读无法写入数据 127.0.0.1:6379> set key1 v1-slave (error) READONLY You can't write against a read only replica. #取消主从复制,在slave上执行 REPLIATOF NO ONE 指令可以取消主从复制 #取消主从复制后,会断开和master的连接不再主从复制, 但不会清除slave上已有的数据 127.0.0.1:6379> REPLICAOF no one OK 127.0.0.1:6379> INFO replication # Replication role:master connected_slaves:0 master_failover_state:no-failover master_replid:4c9236e7046236ebe873d01190864029e9cf508a master_replid2:3ecc9b36d6175a927c0c46bc5681ca340b4f49d0 master_repl_offset:9105 second_repl_offset:9106 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1490 repl_backlog_histlen:7616 127.0.0.1:6379> KEYS * 1) "key1" 127.0.0.1:6379> GET key1 "v1-master"
[root@centos7 ~]#redis-cli 127.0.0.1:6379> AUTH 123456 OK 127.0.0.1:6379> INFO replication # Replication role:master connected_slaves:0 master_failover_state:no-failover master_replid:5c563b18d77232c8b1100322003c015d3c44131c 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 #在slave上设置master的IP和端口 127.0.0.1:6379> REPLICAOF 10.0.0.7 6379 OK #在slave上设置master的密码,才可以同步 127.0.0.1:6379> CONFIG SET masterauth 123456 OK 127.0.0.1:6379> INFO replication # Replication role:slave master_host:10.0.0.7 master_port:6379 master_link_status:up master_last_io_seconds_ago:4 master_sync_in_progress:0 slave_repl_offset:644 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:3ecc9b36d6175a927c0c46bc5681ca340b4f49d0 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:644 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:603 repl_backlog_histlen:42 #在slave2上查看已经同步成功 127.0.0.1:6379> KEYS * 1) "key1" 127.0.0.1:6379> GET key1 "v1-master" #修改slave节点配置文件 [root@centos7 ~]#vim /apps/redis/etc/redis.conf # replicaof1.5 主从复制故障恢复实现replicaof 10.0.0.7 6379 # masterauth masterauth 123456 #重启redis服务 [root@centos7 ~]#systemctl restart redis.service #再次登录查看连接状态 [root@centos7 ~]#redis-cli 127.0.0.1:6379> AUTH 123456 OK 127.0.0.1:6379> INFO replication # Replication role:slave master_host:10.0.0.7 master_port:6379 master_link_status:up master_last_io_seconds_ago:5 master_sync_in_progress:0 slave_repl_offset:5353 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:3ecc9b36d6175a927c0c46bc5681ca340b4f49d0 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:5353 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1490 repl_backlog_histlen:3864 #slave状态只读无法写入数据 127.0.0.1:6379> set key1 v1-slave (error) READONLY You can't write against a read only replica.
master故障后,只能手动提升一个slave为新master,不支持自动切换。
之后将其它的slave节点重新指定新的master为master节点
Master的切换会导致master_replid发生变化,slave之前的master_replid就和当前master不一致,从而会引发所有 slave的全量同步。
假设当前主节点10.0.0.7故障,提升10.0.0.17为新的master
1.51 master[root@centos7 ~]#systemctl stop redis.service1.52 slave 1
127.0.0.1:6379> INFO replication # Replication role:slave master_host:10.0.0.7 master_port:6379 master_link_status:down #显示down,表示无法连接master master_last_io_seconds_ago:-1 master_sync_in_progress:0 slave_repl_offset:11233 master_link_down_since_seconds:241 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:3ecc9b36d6175a927c0c46bc5681ca340b4f49d0 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:11233 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1490 repl_backlog_histlen:9744 #停止slave同步并提升为新的master 127.0.0.1:6379> REPLICAOF NO ONE OK 127.0.0.1:6379> INFO replication # Replication role:master connected_slaves:0 master_failover_state:no-failover master_replid:df2f9e8391795cc0a3b7023b9a90a0b9db553ad3 master_replid2:3ecc9b36d6175a927c0c46bc5681ca340b4f49d0 master_repl_offset:11233 second_repl_offset:11234 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1490 repl_backlog_histlen:9744 #测试能否写入数据 127.0.0.1:6379> set date 20220504 OK 127.0.0.1:6379> get date "20220504" 127.0.0.1:6379> dbsize (integer) 21.53 slave 2
127.0.0.1:6379> INFO replication # Replication role:slave master_host:10.0.0.7 master_port:6379 master_link_status:down master_last_io_seconds_ago:-1 master_sync_in_progress:0 slave_repl_offset:11233 master_link_down_since_seconds:332 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:3ecc9b36d6175a927c0c46bc5681ca340b4f49d0 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:11233 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1490 repl_backlog_histlen:9744 #修改10.0.0.27节点指向新的master节点10.0.0.17 127.0.0.1:6379> REPLICAOF 10.0.0.17 6379 OK 127.0.0.1:6379> INFO replication # Replication role:slave master_host:10.0.0.17 master_port:6379 master_link_status:up master_last_io_seconds_ago:4 master_sync_in_progress:0 slave_repl_offset:11391 slave_priority:100 slave_read_only:1 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:df2f9e8391795cc0a3b7023b9a90a0b9db553ad3 master_replid2:3ecc9b36d6175a927c0c46bc5681ca340b4f49d0 master_repl_offset:11391 second_repl_offset:11234 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1490 repl_backlog_histlen:9902 #查看数据同步 127.0.0.1:6379> get date "20220504" 127.0.0.1:6379> dbsize (integer) 2



