redis主从复制
1 在开启主从赋值的时候,使用的是RDB的方式同步主从数据的
2 同步开始之后,通过主库命令传播的方式,主动复制的方式实现
3 2.8版本以后实现了psync的机制实现断线重连
使用异步复制。
一个主服务器可以有多个从服务器。
从服务器也可以有自己的从服务器。
复制功能不会阻塞主服务器。
可以通过复制功能来让主服务器免于执行持久化操作,由从服务器去执行持久化操作即可。
redis主从复制原理
1. 从服务器向主服务器发送 SYNC 命令。
2. 接到 SYNC 命令的主服务器会调用BGSAVE 命令,创建一个 RDB 文件,并使用缓冲区记录接下来执行的所有写命令。也就是保存快照,然后记录到缓存,从库不需要请求,只需要接收就可以了。
3. 当主服务器执行完 BGSAVE 命令时,它会向从服务器发送 RDB 文件,而从服务器则会接收并载入这个文件。
4. 主服务器将缓冲区储存的所有写命令发送给从服务器执行。
从服务器每秒一次的频率,ping 主服务器一次,并报告复制流的处理情况
主服务器会记录各个从服务器最后一次向他发送ping的时间
用户可以通过配置,指定网络延迟的最大值 min-slaves-max-lag
以及执行写操作所需的至少从服务器数量 min-slaves-to-write
如果至少有min-slaves-to-write个服务器,并且这些服务器延迟值都少于min-slaves-max-lag秒
那么主服务器就会执行客户端的写操作
redis主从会有一个断线重连的机制,当主从断开后,主会保留没有发送的数据,当从服务器好了他会将没有传输的数据传输过去。
主服务器只在有至少 N 个从服务器的情况下,才执行写操作
从 Redis 2.8 开始, 为了保证数据的安全性, 可以通过配置, 让主服务器只在有至少 N 个当前已连接从服务器的情况下, 才执行写命令。
不过, 因为 Redis 使用异步复制, 所以主服务器发送的写数据并不一定会被从服务器接收到, 因此, 数据丢失的可能性仍然是存在的。
通过以下两个参数保证数据的安全:
min-slaves-to-write <number of slaves> #至少有 N 台从库与主库完成同步了则认为主从同步成功
min-slaves-max-lag <number of seconds> #网络延时的最大值,如果大于这个值,认为不成功的
redis主从复制配置[一主两从]
注意: redis没有做数据持久化的时候不要做主从复制,因为一旦主库宕机了,数据都没了,然后通过主从复制将从库数据也重写了,这样会导致重大事故
环境:
主节点:6380
从节点:6381 6382
mkdir /nosql/638{0..2}
vim /nosql/6380/redis.conf
port 6380
daemonize yes
pidfile /nosql/6380/redis.pid
loglevel notice
logfile "/nosql/6380/redis.log"
dbfilename dump.rdb
dir /nosql/6380
protected-mode no
vim /nosql/6381/redis.conf
port 6381
daemonize yes
pidfile /nosql/6381/redis.pid
loglevel notice
logfile "/nosql/6381/redis.log"
dbfilename dump.rdb
dir /nosql/6381
protected-mode no
vim /nosql/6382/redis.conf
port 6382
daemonize yes
pidfile /nosql/6382/redis.pid
loglevel notice
logfile "/nosql/6382/redis.log"
dbfilename dump.rdb
dir /nosql/6382
protected-mode no
启动:
redis-server /nosql/6380/redis.conf
redis-server /nosql/6381/redis.conf
redis-server /nosql/6382/redis.conf
检查:
[root@k8s-master1 redis]# ps -ef|grep redis
root 54840 1 0 19:34 ? 00:00:00 redis-server *:6380
root 54844 1 0 19:34 ? 00:00:00 redis-server *:6381
root 54848 1 0 19:34 ? 00:00:00 redis-server *:6382
开启主从
6381/6382命令行:
[root@k8s-master1 redis]# redis-cli -p 6381
127.0.0.1:6381> SLAVEOF 127.0.0.1 6380 #从哪个机器哪个端口进行复制
OK
127.0.0.1:6381> exit
[root@k8s-master1 redis]# redis-cli -p 6382
127.0.0.1:6382> SLAVEOF 127.0.0.1 6380 #从哪个机器哪个端口进行复制
OK
127.0.0.1:6382> exit
#查询主从状态:
主状态:
[root@k8s-master1 redis]# redis-cli -p 6380
127.0.0.1:6380> info replication
# Replication
role:master
connected_slaves:2 #可以看到从库数量 下面可以看到从库相应状态信息
slave0:ip=127.0.0.1,port=6381,state=online,offset=169,lag=1
slave1:ip=127.0.0.1,port=6382,state=online,offset=169,lag=1
master_repl_offset:169
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:168
从状态:
[root@k8s-master1 redis]# redis-cli -p 6381
127.0.0.1:6381> INFO replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6380
master_link_status:up
master_last_io_seconds_ago:8
master_sync_in_progress:0
slave_repl_offset:113
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
127.0.0.1:6381> exit
------------------------------------------------------------------------
[root@k8s-master1 redis]# redis-cli -p 6382
127.0.0.1:6382> 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:141
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
127.0.0.1:6382> exit
测试主库down了从库替换
#主动停止主库
[root@k8s-master1 redis]# redis-cli -p 6380
127.0.0.1:6380> shutdown
not connected> exit
#检查从库状态
[root@k8s-master1 redis]# redis-cli -p 6381
127.0.0.1:6381> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6380
master_link_status:down #可以检测到master主库down了
master_last_io_seconds_ago:-1
master_sync_in_progress:0
slave_repl_offset:701
master_link_down_since_seconds:35
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
现在需要用 6381从库来替代6380主库,配置如下:
[root@k8s-master1 redis]# redis-cli -p 6381 #选择一个从库连接
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_repl_offset:701
master_link_down_since_seconds:35
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
切换为主库:
127.0.0.1:6381> SLAVEOF no one
OK
从6382查看状态:
[root@k8s-master1 redis]# redis-cli -p 6382
127.0.0.1:6382> 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_repl_offset:701
master_link_down_since_seconds:307
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
可以看到它还在连6380,现在需要把他改为连接到新的主库 6381:
127.0.0.1:6382> SLAVEOF no one
OK
127.0.0.1:6382> SLAVEOF 127.0.0.1 6381
OK
redis 哨兵模式
将原有实验切换回来:
[root@k8s-master1 redis]# redis-server /nosql/6381/redis.conf
[root@k8s-master1 redis]# redis-cli -p 6381
127.0.0.1:6381> SLAVEOF 127.0.0.1 6380
OK
127.0.0.1:6381> exit
[root@k8s-master1 redis]# redis-server /nosql/6382/redis.conf
[root@k8s-master1 redis]# redis-cli -p 6382
127.0.0.1:6382> SLAVEOF 127.0.0.1 6380
OK
127.0.0.1:6382> exit
主库:
[root@k8s-master1 redis]# redis-cli -p 6380
127.0.0.1:6380> INFO replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6381,state=online,offset=127,lag=0
slave1:ip=127.0.0.1,port=6382,state=online,offset=127,lag=0
master_repl_offset:127
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:126
问题:在监控到一个主库出现问题时我们都是自己来通过命令切换,那有没有不需要人工干预
自动切换呢? 接下来了解以下 哨兵模式 它就是解决这个问题的。
sentinel搭建
mkdir /nosql/26380
cd /nosql/26380
vim sentinel.conf 添加以下内容,保存退出
#------------------------------------------
port 26380
dir "/nosql/26380"
sentinel monitor mymaster 127.0.0.1 6380 1
sentinel down-after-milliseconds mymaster 5000
#------------------------------------------
启动:
redis-sentinel /nosql/26380/sentinel.conf &
启动成功提醒:
67226:X 18 Sep 20:29:09.262 # Sentinel ID is 19c19134085099bf08c1d498e050fd51cc651de9
67226:X 18 Sep 20:29:09.262 # +monitor master mymaster 127.0.0.1 6380 quorum 1
67226:X 18 Sep 20:29:09.262 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
67226:X 18 Sep 20:29:09.264 * +slave slave 127.0.0.1:6382 127.0.0.1 6382 @ mymaster 127.0.0.1 6380
67226:X 18 Sep 20:29:11.135 * +sentinel sentinel 8dce82a8f5e8b64c7f7d506c62a4d608d692a587 127.0.0.1 26379 @ mymaster 127.0.0.1 6380
67226:X 18 Sep 20:29:11.140 # +new-epoch 2
66500:X 18 Sep 20:29:11.275 * +sentinel sentinel 19c19134085099bf08c1d498e050fd51cc651de9 127.0.0.1 26380 @ mymaster 127.0.0.1 6380
停止主库测试:
[root@k8s-master1 26380]# redis-cli -p 6380
127.0.0.1:6380> shutdown
not connected> exit
提示信息:
[root@k8s-master1 26380]# redis-cli -p 6380
127.0.0.1:6380> shutdown
not connected> exit
[root@k8s-master1 26380]# 67226:X 18 Sep 20:31:04.775 # +sdown master mymaster 127.0.0.1 6380
67226:X 18 Sep 20:31:04.775 # +odown master mymaster 127.0.0.1 6380 #quorum 1/1
67226:X 18 Sep 20:31:04.775 # +new-epoch 3
67226:X 18 Sep 20:31:04.775 # +try-failover master mymaster 127.0.0.1 6380
67226:X 18 Sep 20:31:04.776 # +vote-for-leader 19c19134085099bf08c1d498e050fd51cc651de9 3
66500:X 18 Sep 20:31:04.778 # +new-epoch 3
66500:X 18 Sep 20:31:04.778 # +vote-for-leader 19c19134085099bf08c1d498e050fd51cc651de9 3
67226:X 18 Sep 20:31:04.779 # 8dce82a8f5e8b64c7f7d506c62a4d608d692a587 voted for 19c19134085099bf08c1d498e050fd51cc651de9 3
66500:X 18 Sep 20:31:04.802 # +sdown master mymaster 127.0.0.1 6380
66500:X 18 Sep 20:31:04.802 # +odown master mymaster 127.0.0.1 6380 #quorum 1/1
66500:X 18 Sep 20:31:04.802 # Next failover delay: I will not start a failover before Fri Sep 18 20:37:05 2020
67226:X 18 Sep 20:31:04.852 # +elected-leader master mymaster 127.0.0.1 6380
67226:X 18 Sep 20:31:04.852 # +failover-state-select-slave master mymaster 127.0.0.1 6380
67226:X 18 Sep 20:31:04.915 # +selected-slave slave 127.0.0.1:6382 127.0.0.1 6382 @ mymaster 127.0.0.1 6380
67226:X 18 Sep 20:31:04.915 * +failover-state-send-slaveof-noone slave 127.0.0.1:6382 127.0.0.1 6382 @ mymaster 127.0.0.1 6380
67226:X 18 Sep 20:31:04.970 * +failover-state-wait-promotion slave 127.0.0.1:6382 127.0.0.1 6382 @ mymaster 127.0.0.1 6380
67226:X 18 Sep 20:31:05.798 # +promoted-slave slave 127.0.0.1:6382 127.0.0.1 6382 @ mymaster 127.0.0.1 6380
67226:X 18 Sep 20:31:05.798 # +failover-state-reconf-slaves master mymaster 127.0.0.1 6380
67226:X 18 Sep 20:31:05.859 * +slave-reconf-sent slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
66500:X 18 Sep 20:31:05.860 # +config-update-from sentinel 19c19134085099bf08c1d498e050fd51cc651de9 127.0.0.1 26380 @ mymaster 127.0.0.1 6380
66500:X 18 Sep 20:31:05.860 # +switch-master mymaster 127.0.0.1 6380 127.0.0.1 6382
66500:X 18 Sep 20:31:05.860 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6382
66500:X 18 Sep 20:31:05.860 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6382
67226:X 18 Sep 20:31:06.812 * +slave-reconf-inprog slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
67226:X 18 Sep 20:31:06.812 * +slave-reconf-done slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
67226:X 18 Sep 20:31:06.868 # +failover-end master mymaster 127.0.0.1 6380
67226:X 18 Sep 20:31:06.868 # +switch-master mymaster 127.0.0.1 6380 127.0.0.1 6382
67226:X 18 Sep 20:31:06.868 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6382
67226:X 18 Sep 20:31:06.868 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6382
66500:X 18 Sep 20:31:10.898 # +sdown slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6382
67226:X 18 Sep 20:31:11.895 # +sdown slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6382
可以看到master切换为了 127.0.0.1 6382
[root@k8s-master1 26380]# redis-cli -p 6382
127.0.0.1:6382> info replication
# Replication
role:master <------------- 6382成了主
connected_slaves:1
slave0:ip=127.0.0.1,port=6381,state=online,offset=30950,lag=0
master_repl_offset:31216
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:31215
重新启动6380
[root@k8s-master1 26380]# redis-server /nosql/6380/redis.conf
提示:
67226:X 18 Sep 20:36:45.117 # -sdown slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6382
66500:X 18 Sep 20:36:45.165 # -sdown slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6382
67226:X 18 Sep 20:36:55.047 * +convert-to-slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6382
查看信息:
[root@k8s-master1 26380]# redis-cli -p 6382
127.0.0.1:6382> INFO replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6381,state=online,offset=65917,lag=1 #
slave1:ip=127.0.0.1,port=6380,state=online,offset=65917,lag=1 # 发现失联的服务器又重新加入到集群了。
master_repl_offset:65917
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:65916
Sentinel管理命令:
redis-cli -p 26380 连接
PING :返回 PONG
SENTINEL masters :列出所有被监视的主服务器
SENTINEL slaves <master name>
SENTINEL get-master-addr-by-name <master name> : 返回给定名字的主服务器的 IP 地址和端口号。
SENTINEL reset <pattern> : 重置所有名字和给定模式 pattern 相匹配的主服务器。
SENTINEL failover <master name> : 当主服务器失效时, 在不询问其他 Sentinel 意见的情况下, 强制开始一次自动故障迁移。