哨兵模式
什么是哨兵模式
主从切换技术的方法是:当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工干预,费事费力,还会造成一段时间内服务不可用。这不是一种推荐的方式,更多时候,我们优先考虑哨兵模式。Redis 从 2.8 开始正式提供了 Sentinel(哨兵)架构来解决这个问题。
反客为主的自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库。
哨兵模式是一种特殊的模式,首先 Redis 提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是 哨兵通过发送命令,等待 Redis 服务器响应,从而监控运行的多个 Redis 实例
这里的哨兵有两个作用:
- 通过发送命令,让 Redis 服务器返回监控其运行状态,包括主服务器和从服务器
- 当哨兵监测到 Master 宕机,会自动将 Slave 切换成 Master,然后通过 发布订阅模式 通知其他的从服务器,修改配置文件,让它们切换主机
然而一个哨兵进程对 Redis 服务器进行监控,可能会出现问题,为此,我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式。
假设主服务器宕机,哨兵 1 先检测到这个结果,系统并不会马上进行 failover 过程,仅仅是哨兵 1 主观的认为主服务器不可用,这个现象成为 主
[root@localhost myredis]# redis-server redis6379.conf
[root@localhost myredis]# redis-cli -p 6379
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:0
master_failover_state:no-failover
master_replid:2d4ec0679594fc160c0ef4bb93885a4976de721c
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:172866
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
观下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行 failover [故障转移]操作。切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为 客观下线。
主从搭建
配置文件目录:
[root@localhost myredis]# ll
total 9736
-rw-r--r--. 1 root root 109048 Nov 24 10:03 6379.conf
-rw-r--r--. 1 root root 109258 Nov 26 18:08 redis6379.conf
-rw-r--r--. 1 root root 109243 Nov 26 18:08 redis6381.conf
-rw-r--r--. 1 root root 109253 Nov 26 18:08 redis6383.conf
-rw-r--r--. 1 root root 906 Nov 26 18:17 sentinel26379.conf
-rw-r--r--. 1 root root 3187708 Nov 26 18:09 sentinel26379.log
-rw-r--r--. 1 root root 902 Nov 26 18:09 sentinel26380.conf
-rw-r--r--. 1 root root 3217213 Nov 26 18:09 sentinel26380.log
-rw-r--r--. 1 root root 906 Nov 26 18:18 sentinel26381.conf
-rw-r--r--. 1 root root 3068640 Nov 26 18:09 sentinel26381.log
-rw-r--r--. 1 root root 701 Nov 26 18:18 sentinel26383.conf
-rw-r--r--. 1 root root 14845 Nov 26 16:28 sentinel.conf
指定配置文件启动服务:81,83执行相同命令
[root@localhost myredis]# redis-server redis6379.conf
[root@localhost myredis]# redis-cli -p 6379
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:0
master_failover_state:no-failover
master_replid:2d4ec0679594fc160c0ef4bb93885a4976de721c
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:172866
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
81,83执行slaveof 127.0.0.1 6379
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:0
master_sync_in_progress:0
slave_read_repl_offset:172908
slave_repl_offset:172908
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:535f2d757afc9a025dd6dbb3046cdffe014f72e7
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:172908
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:172909
repl_backlog_histlen:0
验证主从复制:
127.0.0.1:6381> get k1
"sentinel"
哨兵模式搭建:
指定哨兵配置文件启动服务
[root@localhost myredis]# redis-sentinel sentinel26379.conf
[root@localhost myredis]# redis-sentinel sentinel26381.conf
[root@localhost myredis]# redis-sentinel sentinel26383.conf
[root@localhost myredis]# ps -ef | grep redis
root 974 1 0 20:34 ? 00:00:05 /usr/local/bin/redis-server *:6379
root 2086 1752 0 20:37 pts/0 00:00:00 redis-cli -p 6379
root 2094 1 0 20:37 ? 00:00:04 redis-server *:6381
root 2102 1960 0 20:38 pts/3 00:00:00 redis-cli -p 6381
root 2108 1 0 20:38 ? 00:00:03 redis-server 0.0.0.0:6383
root 2114 1893 0 20:38 pts/2 00:00:00 redis-cli -p 6383
root 2171 1 1 20:48 ? 00:00:00 redis-sentinel 0.0.0.0:26379 [sentinel]
root 2178 1 1 20:48 ? 00:00:00 redis-sentinel 0.0.0.0:26381 [sentinel]
root 2185 1 1 20:48 ? 00:00:00 redis-sentinel 0.0.0.0:26383 [sentinel]
root 2192 1826 0 20:48 pts/1 00:00:00 grep --color=auto redis
开启哨兵之后再次查看主从服务是否正常:
此时83端口为主机,79,81为从机
127.0.0.1:6383> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6381,state=online,offset=186620,lag=1
slave1:ip=127.0.0.1,port=6379,state=online,offset=186755,lag=0
master_failover_state:no-failover
master_replid:87aa05e239e9eafbbae73d43507b8f99587e58bc
master_replid2:614272649bb2a643e89b330eae38282614a78413
master_repl_offset:186755
second_repl_offset:182869
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:172881
repl_backlog_histlen:13875not connected> info replication
# Replication
role:slave
master_host:192.168.58.210
master_port:6383
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0
slave_read_repl_offset:189627
slave_repl_offset:189627
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:7ab016feb00619321abdb637037dcebc1152206f
master_replid2:87aa05e239e9eafbbae73d43507b8f99587e58bc
master_repl_offset:189627
second_repl_offset:187031
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:172909
repl_backlog_histlen:16719not connected> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6383
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0
slave_read_repl_offset:178836
slave_repl_offset:178836
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:ca5d447f255a21ab1ea707a11037149d4873b9dc
master_replid2:535f2d757afc9a025dd6dbb3046cdffe014f72e7
master_repl_offset:178836
second_repl_offset:175095
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:172867
repl_backlog_histlen:5970
验证主从:
127.0.0.1:6383> set k1 sx
Error: Broken pipe
not connected>
not connected> set k1 sx
OKnot connected> get k1
"sx"
主从延迟问题:
127.0.0.1:6379> get k1
Error: Broken pipe
认识broken pipe | pipe是管道的意思,管道里面是数据流,通常是从文件或网络套接字读取的数据。当该管道从另一端突然关闭时,会发生数据突然中断,即是broken,对于socket来说,可能是网络被拔出或另一端的进程崩溃 |
解决问题 | 其实当该异常产生的时候,对于服务端来说,并没有多少影。因为可能是某个客户端突然中止了进程导致了该错误 |
总结 Broken Pipe | 这个异常是客户端读取超时关闭了连接,这时候服务器端再向客户端已经断开的连接写数据时就发生Jbroken pipe异常! |
broken pipe的意思是对端的管道已经断开,往往发生在远端把这个读/写管道关闭了,你无法远端已经发送了FIN序号,告诉你我这个管道已经关闭,这时候,如果你继续往管在对这个管道进行读写操作。从tcp的四次挥手来讲道里写数据,第一次,你会收到一个远端发送的RST号,如果你继续往管道里write数据,操作系统就会给你发送SIGPIPE的信号,并且将errno置为Broken pipe(32),如果你的程序默认没有对SIGPIPE进行处理,那么程序会中断退出。一般情况下,可以用signal(SIGPIPE,SIG IGN)忽略这个信号,这样的话程序不会退出,但是write会返回-1并且将errno置为Brokenpipe(32)。brokenpipe只会出现在往对端已经关闭的管道里写数据的情况下(在收到对端的RST序号后第一次写不会出现broke pipe,而是write返回-1,这时候正确的做法应该是本端也close这个管道,如果继续write,那么就会出现这个错误。
主从挂掉之后重新选举:
将83端口redis服务down掉:
127.0.0.1:6383> SHUTDOWN
not connected>
not connected>
not connected>
not connected> SHUTDOWN
Could not connect to Redis at 127.0.0.1:6383: Connection refused
not connected> SHUTDOWN
Could not connect to Redis at 127.0.0.1:6383: Connection refused
not connected> get k1
Could not connect to Redis at 127.0.0.1:6383: Connection refused
not connected> get k1
Could not connect to Redis at 127.0.0.1:6383: Connection refused
not connected> get k1
Could not connect to Redis at 127.0.0.1:6383: Connection refused
not connected> get k1
Could not connect to Redis at 127.0.0.1:6383: Connection refused
79端口redis重新选举成为主机:
not connected> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6381,state=online,offset=236122,lag=0
master_failover_state:no-failover
master_replid:e0cb76e753ac5037619f68747170e2453fb10b48
master_replid2:fa6d185f6f8346e1890acd5c0959ba97b7b900f2
master_repl_offset:236257
second_repl_offset:235236
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:172867
repl_backlog_histlen:63391
127.0.0.1:6379>
81端口redis为从机:
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:26
master_sync_in_progress:0
slave_read_repl_offset:239692
slave_repl_offset:239692
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:e0cb76e753ac5037619f68747170e2453fb10b48
master_replid2:fa6d185f6f8346e1890acd5c0959ba97b7b900f2
master_repl_offset:239692
second_repl_offset:235236
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:172909
repl_backlog_histlen:66784
旧主机恢复后会不会重新成为主机?
不会!!!!!
83端口
not connected> 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_read_repl_offset:248189
slave_repl_offset:248189
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:392cceec53445a04c012a51a92c5eb8e588c50c8
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:248189
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:247342
repl_backlog_histlen:848
127.0.0.1:6383>