(九)、Redis主从复制
概念
主从复制,主机数据更新后根据配置和策略, 自动同步到备机的master/slaver机制,Master以写为主,Slave以读为主
主从复制环境搭建
复制三个Redis配置文件,分别更改里面的日志文件名称、不同的端口号、RDB文件的名称、快照开启
daemonize yes
logfile "6379.log"
pidfile /var/run/redis_6379.pid
port 6379
dbfilename dump79.rdb
daemonize yes
logfile "6380.log"
pidfile /var/run/redis_6380.pid
port 6380
dbfilename dump80.rdb
daemonize yes
logfile "6381.log"
pidfile /var/run/redis_6381.pid
port 6381
dbfilename dump81.rdb
Redis端口准备完毕
[root@VM-4-15-centos myredis]# ps -ef|grep redis
root 1589 1 0 21:37 ? 00:00:17 redis-server 127.0.0.1:6380
root 1661 1 0 21:37 ? 00:00:14 redis-server 127.0.0.1:6381
root 25093 30799 0 23:23 pts/0 00:00:00 redis-cli -p 6379
root 25162 1192 0 23:23 pts/1 00:00:00 redis-cli -p 6380
root 25305 1289 0 23:24 pts/2 00:00:00 redis-cli -p 6381
查看具体信息,三个机器
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:0
master_failover_state:no-failover
master_replid:792005b03b49fde4d36a9fc24c2c64add164eeeb
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:6380> info replication
# Replication
role:master
connected_slaves:0
master_failover_state:no-failover
master_replid:760bbf4ee817db6ad5a2fb5a41d799ba23854d56
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> info replication
# Replication
role:master
connected_slaves:0
master_failover_state:no-failover
master_replid:5cb1b5303d59b9c7a1624096eedbd821cbc098c7
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
在主机6379
中添加三个数据
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> set k2 v2
OK
127.0.0.1:6379> set k3 v3
OK
从机6380备份
127.0.0.1:6380> keys *
(empty array)
127.0.0.1:6380> slaveof 127.0.0.1 6379
OK
127.0.0.1:6380> keys *
1) "k1"
2) "k2"
3) "k3"
从机6381备份
127.0.0.1:6381> slaveof 127.0.0.1 6379
OK
127.0.0.1:6381> keys *
1) "k2"
2) "k3"
3) "k1"
一主两从模式
一个Master两个Slave
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=266,lag=0
slave1:ip=127.0.0.1,port=6381,state=online,offset=252,lag=1
master_failover_state:no-failover
master_replid:45e9cc2c8fbcaf4447dd2399e2a42a13dccf0707
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:266
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:266
主从备份切入点
从机在备份时候,会从主机从头到尾开始复制过来,无论从机什么时候连接上主机的
从机是否能写入数据
在6381
从机中写入数据失败
127.0.0.1:6381> set k5 v5
(error) READONLY You can't write against a read only replica.
从机不能写入数据,只读
主机关机之后,从机状态
主机6379
关机
127.0.0.1:6379> shutdown
not connected> exit
从机6380
、6381
还是原地待命
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_repl_offset:1298
master_link_down_since_seconds:105
slave_priority:100
slave_read_only:1
connected_slaves:0
master_failover_state:no-failover
master_replid:45e9cc2c8fbcaf4447dd2399e2a42a13dccf0707
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:1298
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:1298
127.0.0.1:6381> 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_repl_offset:1298
master_link_down_since_seconds:97
slave_priority:100
slave_read_only:1
connected_slaves:0
master_failover_state:no-failover
master_replid:45e9cc2c8fbcaf4447dd2399e2a42a13dccf0707
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:1298
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:127
repl_backlog_histlen:1172
主机恢复之后,从机数据能否保持一致
主机6379
重新连接,并新增一条数据
[root@VM-4-15-centos myredis]# redis-server /root/myredis/redis79.conf
[root@VM-4-15-centos myredis]# redis-cli -p 6379
127.0.0.1:6379> keys *
1) "k4"
2) "k3"
3) "k1"
4) "k2"
127.0.0.1:6379> set k5 v5
OK
6381
、6380
从机会继续备份
127.0.0.1:6381> keys *
1) "k4"
2) "k5"
3) "k2"
4) "k3"
5) "k1"
从机断开一段时间之后,数据能否一致
6380
从机关机
127.0.0.1:6380> shutdown
not connected> exit
在主机6379
中新增数据
127.0.0.1:6379> keys *
1) "k5"
2) "k2"
3) "k1"
4) "k3"
5) "k4"
127.0.0.1:6379> set k6 v6
OK
在另一个6381
从机中查询
127.0.0.1:6381> get k6
"v6"
这时候从机6380
恢复
[root@VM-4-15-centos ~]# redis-server /root/myredis/redis80.conf
[root@VM-4-15-centos ~]# redis-cli -p 6380
查看信息已经和主机断连,不再是从机状态
127.0.0.1:6380> info replication
# Replication
role:master
connected_slaves:0
master_failover_state:no-failover
master_replid:caece3e0a3cb3c2eb950267241ce5ab304efd8bd
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
这时候主机6379
新增一条数据
127.0.0.1:6379> set k9 v9
OK
从机6380
查询不到
127.0.0.1:6380> get k9
(nil)
每次从机和master主机断开之后需要重新连接,除非写进配置文件自动重连,具体位置redis.conf搜寻#### REPLICATION ####
从机上位模式
使当前数据库停止与其他数据库的同步,转成主数据库
SLAVEOF no one
薪火相传模式
- 上一个Slave可以是下一个slave的Master,Slave同样可以接收其他 slaves的连接和同步请求,那么该slave作为了链条中下一个的master, 可以有效减轻master的写压力(奴隶的奴隶还是奴隶)
- 中途变更转向:会清除之前的数据,重新建立拷贝最新的
- slaveof 新主库IP 新主库端口
复制原理
slave启动成功连接到master后会发送一个sync命令
master接到命令启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令, 在后台进程执行完毕之后,master将传送整个数据文件到slave,以完成一次完全同步
全量复制:而slave服务在接收到数据库文件数据后,将其存盘并加载到内存中。
增量复制:Master继续将新的所有收集到的修改命令依次传给slave,完成同步
但是只要是重新连接master,一次完全同步(全量复制)将被自动执行
哨兵模式
能够自动监控主机,如果主机挂了,在剩余的从机里面用投票的方式决定新的主机
哨兵模式配置
6379为主机,6380、6381为从机
创建一个文件,配置哨兵
[root@VM-4-15-centos myredis]# touch sentinel.conf
[root@VM-4-15-centos myredis]# vim sintinel.conf
sentinel monitor host6379 127.0.0.1 6379 1
最后一个数字1,表示主机挂掉后salve投票看让谁接替成为主机,得票数多少后成为主机
启动哨兵
在redis安装目录下启动,哨兵开始巡逻
[root@VM-4-15-centos redis-6.2.1]# redis-sentinel /root/myredis/sentinel.conf
30353:X 16 Aug 2021 22:46:55.419 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
30353:X 16 Aug 2021 22:46:55.419 # Redis version=6.2.1, bits=64, commit=00000000, modified=0, pid=30353, just started
30353:X 16 Aug 2021 22:46:55.419 # Configuration loaded
30353:X 16 Aug 2021 22:46:55.419 * monotonic clock: POSIX clock_gettime
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 6.2.1 (00000000/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in sentinel mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 26379
| `-._ `._ / _.-' | PID: 30353
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | http://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
30353:X 16 Aug 2021 22:46:55.420 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
30353:X 16 Aug 2021 22:46:55.420 # Sentinel ID is 8206264712b3f0688eb364d8e1353eec683fb659
30353:X 16 Aug 2021 22:46:55.420 # +monitor master host6379 127.0.0.1 6379 quorum 1
30353:X 16 Aug 2021 22:46:55.422 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ host6379 127.0.0.1 6379
30353:X 16 Aug 2021 22:46:55.434 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ host6379 127.0.0.1 6379
关闭主机6379
127.0.0.1:6379> shutdown
not connected> exit
等待哨兵巡逻投票新的主机
0353:X 16 Aug 2021 22:49:33.543 # +new-epoch 1
30353:X 16 Aug 2021 22:49:33.543 # +try-failover master host6379 127.0.0.1 6379
30353:X 16 Aug 2021 22:49:33.549 # +vote-for-leader 8206264712b3f0688eb364d8e1353eec683fb659 1
30353:X 16 Aug 2021 22:49:33.549 # +elected-leader master host6379 127.0.0.1 6379
30353:X 16 Aug 2021 22:49:33.549 # +failover-state-select-slave master host6379 127.0.0.1 6379
30353:X 16 Aug 2021 22:49:33.632 # +selected-slave slave 127.0.0.1:6380 127.0.0.1 6380 @ host6379 127.0.0.1 6379
30353:X 16 Aug 2021 22:49:33.632 * +failover-state-send-slaveof-noone slave 127.0.0.1:6380 127.0.0.1 6380 @ host6379 127.0.0.1 6379
30353:X 16 Aug 2021 22:49:33.732 * +failover-state-wait-promotion slave 127.0.0.1:6380 127.0.0.1 6380 @ host6379 127.0.0.1 6379
30353:X 16 Aug 2021 22:49:33.973 # +promoted-slave slave 127.0.0.1:6380 127.0.0.1 6380 @ host6379 127.0.0.1 6379
30353:X 16 Aug 2021 22:49:33.973 # +failover-state-reconf-slaves master host6379 127.0.0.1 6379
30353:X 16 Aug 2021 22:49:34.022 * +slave-reconf-sent slave 127.0.0.1:6381 127.0.0.1 6381 @ host6379 127.0.0.1 6379
30353:X 16 Aug 2021 22:49:35.015 * +slave-reconf-inprog slave 127.0.0.1:6381 127.0.0.1 6381 @ host6379 127.0.0.1 6379
30353:X 16 Aug 2021 22:49:35.015 * +slave-reconf-done slave 127.0.0.1:6381 127.0.0.1 6381 @ host6379 127.0.0.1 6379
30353:X 16 Aug 2021 22:49:35.086 # +failover-end master host6379 127.0.0.1 6379
30353:X 16 Aug 2021 22:49:35.086 # +switch-master host6379 127.0.0.1 6379 127.0.0.1 6380
30353:X 16 Aug 2021 22:49:35.086 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ host6379 127.0.0.1 6380
30353:X 16 Aug 2021 22:49:35.086 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ host6379 127.0.0.1 6380
30353:X 16 Aug 2021 22:50:05.090 # +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ host6379 127.0.0.1 6380
最后主机为6380
127.0.0.1:6380> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6381,state=online,offset=20619,lag=1
master_failover_state:no-failover
master_replid:9decacfce1e69d40a1cd37600881919ab4ef464d
master_replid2:eec2ebe84740b484344d0e4ffba5cdc29e0d5c54
master_repl_offset:20619
second_repl_offset:10146
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:20619
当之前挂掉的主机6379重新连接上,这时候还是单独的主机
[root@VM-4-15-centos ~]# redis-server /root/myredis/redis79.conf
[root@VM-4-15-centos ~]# redis-cli -p 6379
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:0
master_failover_state:no-failover
master_replid:a911210268512fd5125a73fe0db7a5175126d161
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
过一会被哨兵监控到,挂了的master重启回来,会变成slave
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6380
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:32598
slave_priority:100
slave_read_only:1
connected_slaves:0
master_failover_state:no-failover
master_replid:9decacfce1e69d40a1cd37600881919ab4ef464d
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:32598
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:28369
repl_backlog_histlen:4230
复制延时
由于所有的写操作都是先在Master上操作,然后同步更新到slave上,所以从Master同步到Slave机器有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,Slave机器数量的增加也会使这个问题更加严重。