主从切换技术的方法是:当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工干预,费事费力,还会造成一段时间内服务不可用。这不是一种推荐的方式,更多时候,我们优先考虑哨兵模式。
哨兵模式概述:
哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。
这里的哨兵有两个作用
通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器。
当哨兵监测到master宕机,会自动将slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机。
然而一个哨兵进程对Redis服务器进行监控,可能会出现问题,为此,我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式。
用文字描述一下故障切换(failover)的过程。假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行failover过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象成为主观下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行failover操作。切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线。这样对于客户端而言,一切都是透明的
有关原理可以参考: redis中文文档参考
实验环境:
server1 | 172.25.75.1 | master |
---|---|---|
server2 | 172.25.75.2 | slave |
server3 | 172.25.75.3 | slave |
[root@server1 ~]# ls
redis-5.0.3.tar.gz
[root@server1 ~]# tar zxf redis-5.0.3.tar.gz
[root@server1 ~]# ls
redis-5.0.3 redis-5.0.3.tar.gz
[root@server1 ~]# cd redis-5.0.3
[root@server1 redis-5.0.3]# ls
00-RELEASENOTES CONTRIBUTING deps Makefile README.md runtest runtest-sentinel src utils
BUGS COPYING INSTALL MANIFESTO redis.conf runtest-cluster sentinel.conf tests
[root@server1 redis-5.0.3]# yum install gcc -y
[root@server1 redis-5.0.3]# make
[root@server1 redis-5.0.3]# make install
server1:
[root@server1 ~]# ls
redis-5.0.3 redis-5.0.3.tar.gz
[root@server1 ~]# scp -r redis-5.0.3 [email protected]:
server2、server3:
cd redis-5.0.3/
make install
cd src && make install
make[1]: Entering directory `/root/redis-5.0.3/src'
Hint: It's a good idea to run 'make test' ;)
INSTALL install
INSTALL install
INSTALL install
INSTALL install
INSTALL install
make[1]: Leaving directory `/root/redis-5.0.3/src'
[root@server1 ~]# cd redis-5.0.3/utils/
[root@server1 utils]# ls
build-static-symbols.tcl generate-command-help.rb install_server.sh redis_init_script.tpl whatisdoing.sh
cluster_fail_time.tcl graphs lru redis-sha1.rb
corrupt_rdb.c hashtable redis-copy.rb releasetools
create-cluster hyperloglog redis_init_script speed-regression.tcl
[root@server1 utils]# ./install_server.sh
Welcome to the redis service installer
This script will help you easily set up a running redis server
Please select the redis port for this instance: [6379]
Selecting default: 6379
Please select the redis config file name [/etc/redis/6379.conf]
Selected default - /etc/redis/6379.conf
Please select the redis log file name [/var/log/redis_6379.log]
Selected default - /var/log/redis_6379.log
Please select the data directory for this instance [/var/lib/redis/6379]
Selected default - /var/lib/redis/6379
Please select the redis executable path [/usr/local/bin/redis-server]
Selected config:
Port : 6379
Config file : /etc/redis/6379.conf
Log file : /var/log/redis_6379.log
Data dir : /var/lib/redis/6379
Executable : /usr/local/bin/redis-server
Cli Executable : /usr/local/bin/redis-cli
Is this ok? Then press ENTER to go on or Ctrl-C to abort.
Copied /tmp/6379.conf => /etc/init.d/redis_6379
Installing service...
Successfully added to chkconfig!
Successfully added to runlevels 345!
Starting Redis server...
Installation successful!
[root@server1 utils]# netstat -antplu
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 16809/redis-server
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 902/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1520/master
tcp 0 0 172.25.75.1:22 172.25.75.250:58266 ESTABLISHED 2109/sshd: root@pts
tcp6 0 0 :::22 :::* LISTEN 902/sshd
tcp6 0 0 ::1:25 :::* LISTEN 1520/master
修改配置文件:
[root@server1 utils]# vim /etc/redis/6379.conf
70 bind 0.0.0.0
[root@server1 utils]# /etc/init.d/redis_6379 restart #不要用systemctl(可能会没效果)
Stopping ...
Redis stopped
Starting Redis server...
[root@server1 utils]# netstat -antplu #发现端口号修改了
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN 16822/redis-server
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 902/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1520/master
tcp 0 0 127.0.0.1:6379 127.0.0.1:42572 TIME_WAIT -
tcp 0 0 172.25.75.1:22 172.25.75.250:58266 ESTABLISHED 2109/sshd: root@pts
tcp6 0 0 :::22 :::* LISTEN 902/sshd
tcp6 0 0 ::1:25 :::* LISTEN 1520/master
我们以servser2为例子:
[root@server2 redis-5.0.3]# cd utils/
[root@server2 utils]# ./install_server.sh
[root@server2 utils]# vim /etc/redis/6379.conf
70 bind 0.0.0.0
[root@server2 utils]# /etc/init.d/redis_6379 restart
Stopping ...
Redis stopped
Starting Redis server...
[root@server2 utils]# netstat -tnlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN 12481/redis-server
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 856/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1168/master
tcp6 0 0 :::22 :::* LISTEN 856/sshd
tcp6 0 0 ::1:25 :::* LISTEN 1168/master
server2-3:
[root@server2 utils]# vim /etc/redis/6379.conf
1380 slaveof 172.25.75.1 6379
[root@server2 utils]# /etc/init.d/redis_6379 restart
Stopping ...
Redis stopped
Starting Redis server...
server1:
[root@server1 utils]# redis-cli
127.0.0.1:6379> info
# Replication
role:master #自己为master
connected_slaves:2
slave0:ip=172.25.75.2,port=6379,state=online,offset=210,lag=0 #两个从属节点
slave1:ip=172.25.75.3,port=6379,state=online,offset=210,lag=0
master_replid:320e30394da07701e84575ddcf907b1a4bb989db
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:224
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:224
127.0.0.1:6379> set name zhao #master拥有读写权限
OK
127.0.0.1:6379> get name
"zhao"
[root@server2 utils]# redis-cli
127.0.0.1:6379> info
# Replication
role:slave
master_host:172.25.75.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:2
master_sync_in_progress:0
slave_repl_offset:280
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:320e30394da07701e84575ddcf907b1a4bb989db
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:6379> get name #slave节点只有可读权限
"zhao"
127.0.0.1:6379> set name liu
(error) READONLY You can't write against a read only replica.
server1:
[root@server1 redis-5.0.3]# pwd
/root/redis-5.0.3
[root@server1 redis-5.0.3]# cp sentinel.conf /etc/redis/
[root@server1 redis-5.0.3]# cd /etc/redis/
[root@server1 redis]# vim sentinel.conf
17 protected-mode no #关闭
84 sentinel monitor mymaster 172.25.75.1 6379 2 #mymaster是名字, 2表示2个slave
113 sentinel down-after-milliseconds mymaster 10000 #等待10s
发送哨兵配置文件给其他slave节点
[root@server1 redis]# scp sentinel.conf server2:/etc/redis/
sentinel.conf 100% 9710 9.5KB/s 00:00
[root@server1 redis]# scp sentinel.conf server3:/etc/redis/
sentinel.conf 100% 9710 9.5KB/s 00:00
[root@server1 redis]# redis-server /etc/redis/sentinel.conf --sentinel
[root@server2 ~]# redis-server /etc/redis/sentinel.conf --sentinel
[root@server3 ~]# redis-server /etc/redis/sentinel.conf --sentinel
master的结果:
可以看到信息,server1为master,server2-3都是slave节点。
重新开启一个终端远程连接server1查看端口发现哨兵26379进程开启:
进入redis数据库:
[root@server1 ~]# redis-cli
127.0.0.1:6379> info #查看状态信息,此时server1是master
# Replication
role:master
connected_slaves:2
slave0:ip=172.25.75.2,port=6379,state=online,offset=59072,lag=0
slave1:ip=172.25.75.3,port=6379,state=online,offset=59072,lag=0
查看26479端口:
[root@server1 ~]# redis-cli -p 26379
127.0.0.1:26379> info
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=172.25.75.1:6379,slaves=2,sentinels=3
注意:此时显示主是server1,sentinels=3表示成功
测试:
将server1的redis-cli关闭
[root@server1 ~]# redis-cli
127.0.0.1:6379> SHUTDOWN
not connected>
此时redis会随机选择一个slave作master:
我们可以看到此时哨兵为我们挑选了server3作为新的master!!!
我们从server2上查看信息:
master已经更改为server3了!!!
我们在新的master上写入信息,再在server2上查看: