一. redis主从配置
1.三台机器部署redis
主机名称 IP地址 redis版本
redis-master 192.168.2.32 redis 5.0.5(主)
redis-slave01 192.168.2.34 redis 5.0.5(从)
redis-slave02 192.168.2.35 redis 5.0.5(从)
2.修改主从redis的配置文件
master的主要配置文件
[root@base-master redis]# grep -Ev "^$|#" redis.conf
bind 0.0.0.0
protected-mode yes
port 6379
tcp-keepalive 300
daemonize yes
pidfile "/var/run/redis_6379.pid"
loglevel notice
logfile "/opt/redis/logs/redis.log"
dbfilename "dump.rdb"
dir "/opt/redis"
slave1的配置文件
bind 0.0.0.0
protected-mode yes
port 6379
tcp-keepalive 300
daemonize yes
pidfile "/var/run/redis_6379.pid"
loglevel notice
logfile "/opt/redis/logs/redis.log"
dbfilename "dump.rdb"
dir "/opt/redis"
replicaof 192.168.2.32 6379 # 添加master的内网ip和端口
masterauth 123456 # 如果master上有密码配置,这里配置master的密码
slave2的配置文件
bind 0.0.0.0
protected-mode yes
port 6379
tcp-keepalive 300
daemonize yes
pidfile "/var/run/redis_6379.pid"
loglevel notice
logfile "/opt/redis/logs/redis.log"
dbfilename "dump.rdb"
dir "/opt/redis"
replicaof 192.168.2.32 6379 #添加master的内网ip和端口
masterauth 123456 #如果master上有密码配置,这里配置master的密码
启动主从redis
三台都启动redis
[root@base-master redis]# ./src/redis-server ./redis.conf
[root@base-slave1 redis]# ./src/redis-server ./redis.conf
[root@base-slave2 redis]# ./src/redis-server ./redis.conf
[root@base-master redis]# ps -ef | grep redis
root 1135 1 0 9月21 ? 00:00:50 ./src/redis-server 0.0.0.0:6379
[root@base-slave1 redis]# ps -ef | grep redis
root 1135 1 0 9月21 ? 00:00:50 ./src/redis-server 0.0.0.0:6379
[root@base-slave2 redis]# ps -ef | grep redis
root 1135 1 0 9月21 ? 00:00:50 ./src/redis-server 0.0.0.0:6379
主从测试
1.在master上面执行
[root@redis-master redis]# cd src/
[root@redis-master src]# ./redis-cli
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> set name xuan
OK
127.0.0.1:6379> get name
"xuan"
127.0.0.1:6379>
2.分别在slave-1和slave-2上面执行:
[root@redis-slave-1 redis]# cd src/
[root@redis-slave-1 src]# ./redis-cli
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> get name
"xuan"
127.0.0.1:6379>
[root@redis-slave-2 src]# ./redis-cli
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> get name "xuan"
127.0.0.1:6379>
3.查看复制状态
master执行:
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.2.34,port=6379,state=online,offset=482568,lag=0
slave1:ip=192.168.2.35,port=6379,state=online,offset=482427,lag=1
master_replid:a67fca6ff5a6910f3f23b800a0bf973d2ae52cfc
master_replid2:e92bde36e46617f457b68275e4ea6df7ed46c381
master_repl_offset:482850
second_repl_offset:21196
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:482850
slave上面执行:
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:192.168.2.32
master_port:6379
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0
slave_repl_offset:503405
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:a67fca6ff5a6910f3f23b800a0bf973d2ae52cfc
master_replid2:e92bde36e46617f457b68275e4ea6df7ed46c381
master_repl_offset:503405
second_repl_offset:21196
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:3013
repl_backlog_histlen:500393
主从同步部署完成!
二、Redis-sentinel哨兵模式
1、哨兵简介:Redis Sentinel
Sentinel(哨兵)是用于监控redis集群中Master状态的工具,其已经被集成在redis2.4+的版本中是Redis官方推荐
的高可用性(HA)解决方案。
2、作用
1):Master状态检测
2):如果Master异常,则会进行Master-Slave切换,将其中一个Slave作为Master,将之前的Master作为Slave
3):Master-Slave切换后,master_redis.conf、slave_redis.conf和sentinel.conf的内容都会发生改变,即master_redis.conf中会多一行slaveof的配置,sentinel.conf的监控目标会随之调换
3、工作模式
1):每个Sentinel以每秒钟一次的频率向它所知的Master,Slave以及其他 Sentinel 实例发送一个 PING 命令
2):如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被 Sentinel 标记为主观下线。
3):如果一个Master被标记为主观下线,则正在监视这个Master的所有 Sentinel 要以每秒一次的频率确认Master的确进入了主观下线状态。
4):当有足够数量的 Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认Master的确进入了主观下线状态, 则Master会被标记为客观下线
4、主观下线和客观下线
主观下线:Subjectively Down,简称 SDOWN,指的是当前 Sentinel 实例对某个redis服务器做出的下线判断。
客观下线:Objectively Down, 简称 ODOWN,指的是多个 Sentinel 实例在对Master Server做出 SDOWN 判断,并且通过 SENTINE SENTINEL is-master-down-by-addr 命令互相交流之后,得出的Master Server下线判断,然后开启failover
5、配置哨兵模式
主机名称 IP地址
redis-master 192.168.2.32:6379 redis 5.0.5(主)
redis-slave01 192.168.2.34:6379 redis 5.0.5(从)
redis-slave02 192.168.2.35:6379 redis 5.0.5(从)
redis-master 192.168.2.32:26379 Sentinel01
redis-slave01 192.168.2.34:26379 Sentinel02
redis-slave02 192.168.2.35:26379 Sentinel03
Sentinel.conf配置文件主要参数解析:
# 端口
port 26379
# 是否后台启动
daemonize yes
# pid文件路径
pidfile /var/run/redis-sentinel.pid
# 日志文件路径
logfile "/var/log/sentinel.log"
# 定义工作目录
dir /tmp
# 定义Redis主的别名, IP, 端口,这里的2指的是需要至少2个Sentinel认为主Redis挂了才最终会采取下一步行为
sentinel monitor mymaster 127.0.0.1 6379 2
# 如果mymaster 30秒内没有响应,则认为其主观失效
sentinel down-after-milliseconds mymaster 30000
# 如果master重新选出来后,其它slave节点能同时并行从新master同步数据的台数有多少个,显然该值越大,所有slave节点完成同步切换的整体速度越快,但如果此时正好有人在访问这些slave,可能造成读取失败,影响面会更广。最保守的设置为1,同一时间,只能有一台干这件事,这样其它slave还能继续服务,但是所有slave全部完成缓存更新同步的进程将变慢。
sentinel parallel-syncs mymaster 1
# 该参数指定一个时间段,在该时间段内没有实现故障转移成功,则会再一次发起故障转移的操作,单位毫秒
sentinel failover-timeout mymaster 180000
# 不允许使用SENTINEL SET设置notification-script和client-reconfig-script。
sentinel deny-scripts-reconfig yes
修改三台Sentinel的配置文件,如下
[root@base-master redis]# grep -Ev "^$|#" sentinel.conf
port 26379
daemonize yes
pidfile "/var/run/redis-sentinel.pid"
logfile "/opt/redis/logs/sentinel.log"
dir "/tmp"
sentinel deny-scripts-reconfig yes
sentinel monitor mymaster 192.168.2.32 6379 2
sentinel failover-timeout mymaster 10000
sentinel auth-pass mymaster 123456 # 如果redis设置了密码,配置一下
[root@base-slave1 redis]# grep -Ev "^$|#" sentinel.conf
port 26379
daemonize yes
pidfile "/var/run/redis-sentinel.pid"
logfile "/opt/redis/logs/sentinel.log"
dir "/tmp"
sentinel deny-scripts-reconfig yes
sentinel monitor mymaster 192.168.2.32 6379 2
sentinel failover-timeout mymaster 10000
sentinel auth-pass mymaster 123456 # 如果redis设置了密码,配置一下
[root@base-slave2 redis]# grep -Ev "^$|#" sentinel.conf
port 26379
daemonize yes
pidfile "/var/run/redis-sentinel.pid"
logfile "/opt/redis/logs/sentinel.log"
dir "/tmp"
sentinel deny-scripts-reconfig yes
sentinel monitor mymaster 192.168.2.32 6379 2
sentinel failover-timeout mymaster 10000
sentinel auth-pass mymaster 123456 # 如果redis设置了密码,配置一下
每台机器启动哨兵服务:
[root@redis-master redis]# ./src/redis-sentinel sentinel.conf
[root@redis-slave1 redis]# ./src/redis-sentinel sentinel.conf
[root@redis-slave2 redis]# ./src/redis-sentinel sentinel.conf
查看信息
[root@base-master redis]# redis-cli -p 26379
127.0.0.1:26379> ping
PONG
127.0.0.1:26379> sentinel master mymaster #主节点的状态信息
1) "name"
2) "mymaster"
3) "ip"
4) "192.168.2.32"
5) "port"
6) "6379"
7) "runid"
8) "d92a445b7a680df2e0d931edb1b4d1f42471d08d"
9) "flags"
10) "master"
........
127.0.0.1:26379> sentinel slaves mymaster #查看mymaster的从信息,可以看到有2个从节点
1) 1) "name"
2) "192.168.2.35:6379"
3) "ip"
4) "192.168.2.35"
5) "port"
6) "6379"
7) "runid"
8) "23ace834a24e91d81a4ee162ffff123bc0b3754a"
9) "flags"
10) "slave"
......
2) 1) "name"
2) "192.168.2.34:6379"
3) "ip"
4) "192.168.2.34"
5) "port"
6) "6379"
7) "runid"
8) "e48433d94642f8774846e4a235f8500ccc18a860"
9) "flags"
10) "slave"
.....
127.0.0.1:26379> sentinel sentinels mymaster #查看其它sentinel信息
1) 1) "name"
2) "fb12c5486b6ce0995a89f4aaadf69a9800056aa2"
3) "ip"
4) "192.168.2.34"
5) "port"
6) "26379"
7) "runid"
8) "fb12c5486b6ce0995a89f4aaadf69a9800056aa2"
9) "flags"
10) "sentinel"
11) "link-pending-commands"
12) "0"
13) "link-refcount"
14) "1"
15) "last-ping-sent"
16) "0"
17) "last-ok-ping-reply"
18) "564"
19) "last-ping-reply"
20) "564"
21) "down-after-milliseconds"
22) "30000"
23) "last-hello-message"
24) "976"
25) "voted-leader"
26) "?"
27) "voted-leader-epoch"
28) "18"
2) 1) "name"
2) "2daa2da905fbb00c126ab2882d8903b34142e71b"
3) "ip"
4) "192.168.2.35"
5) "port"
6) "26379"
7) "runid"
8) "2daa2da905fbb00c126ab2882d8903b34142e71b"
9) "flags"
10) "sentinel"
11) "link-pending-commands"
12) "0"
13) "link-refcount"
14) "1"
15) "last-ping-sent"
16) "0"
17) "last-ok-ping-reply"
18) "564"
19) "last-ping-reply"
20) "564"
21) "down-after-milliseconds"
22) "30000"
23) "last-hello-message"
24) "615"
25) "voted-leader"
26) "?"
27) "voted-leader-epoch"
28) "18"
哨兵测试
停掉master的redis
[root@base-master redis]# ps -ef | grep redis
root 4076 1 0 9月17 ? 00:07:16 ./src/redis-sentinel *:26379 [sentinel]
root 22406 1 0 08:34 ? 00:00:03 ../src/redis-server 0.0.0.0:6379
root 28813 32006 0 09:54 pts/0 00:00:00 grep --color=auto redis
[root@base-master redis]# kill -9 22406
[root@base-master redis]# ps -ef | grep redis
root 4076 1 0 9月17 ? 00:07:16 ./src/redis-sentinel *:26379 [sentinel]
root 28842 32006 0 09:54 pts/0 00:00:00 grep --color=auto redis
查看哨兵日志
[root@base-slave1 logs]# tailf sentinel.log
19142:X 22 Sep 2020 09:55:11.405 # +sdown master mymaster 192.168.2.32 6379 #master主服务已宕机
19142:X 22 Sep 2020 09:55:11.471 # +odown master mymaster 192.168.2.32 6379 #quorum 2/2
19142:X 22 Sep 2020 09:55:11.471 # +new-epoch 19
19142:X 22 Sep 2020 09:55:11.471 # +try-failover master mymaster 192.168.2.32 6379 # 开始故障恢复
19142:X 22 Sep 2020 09:55:11.472 # +vote-for-leader fb12c5486b6ce0995a89f4aaadf69a9800056aa2 19
19142:X 22 Sep 2020 09:55:11.476 # 2daa2da905fbb00c126ab2882d8903b34142e71b voted for fb12c5486b6ce0995a89f4aaadf69a9800056aa2 19 #投票选举哨兵leader
19142:X 22 Sep 2020 09:55:11.476 # a928076f96ca0580be30eb089b63d2a189dc87e5 voted for fb12c5486b6ce0995a89f4aaadf69a9800056aa2 19
19142:X 22 Sep 2020 09:55:11.543 # +elected-leader master mymaster 192.168.2.32 6379 # 选中哨兵leader
19142:X 22 Sep 2020 09:55:11.543 # +failover-state-select-slave master mymaster 192.168.2.32 6379 #选中其中一个slave当作master
19142:X 22 Sep 2020 09:55:11.602 # +selected-slave slave 192.168.2.35:8700 192.168.2.35 6379 @ mymaster 192.168.2.32 6379 #选中192.168.2.35
19142:X 22 Sep 2020 09:55:11.602 * +failover-state-send-slaveof-noone slave 192.168.2.35:6379 192.168.2.35 6379 @ mymaster 192.168.2.32 6379 #发送slaveof no one 命令
19142:X 22 Sep 2020 09:55:11.678 * +failover-state-wait-promotion slave 192.168.2.35:6379 192.168.2.35 6379 @ mymaster 192.168.2.32 6379
19142:X 22 Sep 2020 09:55:11.737 # +promoted-slave slave 192.168.2.35:6379 192.168.2.35 6379 @ mymaster 192.168.2.32 6379 #等待35升级为master
19142:X 22 Sep 2020 09:55:11.737 # +failover-state-reconf-slaves master mymaster 192.168.2.32 6379
19142:X 22 Sep 2020 09:55:11.820 * +slave-reconf-sent slave 192.168.2.34:6379 192.168.2.34 6379 @ mymaster 192.168.2.32 6379 #34正在设置新的master
19142:X 22 Sep 2020 09:55:12.149 * +slave-reconf-inprog slave 192.168.2.34:6379 192.168.2.34 6379 @ mymaster 192.168.2.32 6379
19142:X 22 Sep 2020 09:55:12.568 # -odown master mymaster 192.168.2.32 6379
19142:X 22 Sep 2020 09:55:13.171 * +slave-reconf-done slave 192.168.2.34:6379 192.168.2.34 6379 @ mymaster 192.168.2.32 6379
19142:X 22 Sep 2020 09:55:13.223 # +failover-end master mymaster 192.168.2.32 6379 #故障转移完成
19142:X 22 Sep 2020 09:55:13.223 # +switch-master mymaster 192.168.2.32 6379 192.168.2.35 6379 #master从32转移到35
19142:X 22 Sep 2020 09:55:13.224 * +slave slave 192.168.2.34:6379 192.168.2.34 6379 @ mymaster 192.168.2.35 6379 #添加32为35的从节点
19142:X 22 Sep 2020 09:55:13.224 * +slave slave 192.168.2.32:6379 192.168.2.32 6379 @ mymaster 192.168.2.35 6379 3 #添加34为35的从节点
4076:X 22 Sep 2020 10:12:42.471 # +sdown slave 192.168.2.32:8700 192.168.2.32 8700 @ mymaster 192.168.2.35 8700 #32已宕机 等待修复
从上面的日志可以看到master已经down,并切换为192.168.2.35为master节点
三 . 用vip实现实现高可用
客户端程序连接redis时需要ip和port,但redis-server进行故障转移时,主redis是变化的,所以ip地址也是变化的。客户端程序如何感知当前主redis的ip地址和端口呢?
redis-sentinel提供了接口,请求任何一个sentinel,发送SENTINEL get-master-addr-by-name <master name>就能得到当前主redis的ip和port。
获取当前主redis的ip和port:
[root@base-master redis]# redis-cli -p 26379
127.0.0.1:26379> SENTINEL get-master-addr-by-name mymaster
1) "192.168.2.35"
2) "6379"
VIP方案是,redis系统对外始终是同一ip地址,当redis进行故障转移时,需要做的是将VIP从之前的redis服务器漂移到现在新的主redis服务器上。
这里可以使用redis sentinel的一个参数client-reconfig-script,这个参数配置执行脚本,sentinel在做failover的时候会执行这个脚本,并且传递6个参数<master-name>、 <role>、 <state>、 <from-ip>、 <from-port>、 <to-ip> 、<to-port>,其中<to-ip>是新主redis的IP地址,可以在这个脚本里做VIP漂移操作
sentinel client-reconfig-script mymaster /scripts/notify_master.sh
修改三个服务器的redis-sentinel配置文件sentinel.conf,增加上面一行。然后在/scripts目录下创建notify_master.sh脚本文件,这个脚本做VIP漂移操作,内容如下:
脚本内容
#!/bin/bash
MASTER_IP=$6 #第六个参数是新主redis的ip地址
LOCAL_IP='192.168.2.35' #本机ip
VIP='192.168.2.201'
NETMASK='24'
INTERFACE='eth0'
if [ ${MASTER_IP} = ${LOCAL_IP} ];then
/sbin/ip addr add ${VIP}/${NETMASK} dev ${INTERFACE} #将VIP绑定到该服务器上
/sbin/arping -q -c 3 -U ${VIP} -I ${INTERFACE}
exit 0
else
/sbin/ip addr del ${VIP}/${NETMASK} dev ${INTERFACE} #将VIP从该服务器上删除
exit 0
fi
exit 1 #如果返回1,sentinel会一直执行这个脚本
现在当前主redis是192.168.2.35,需要手动绑定VIP到该服务器上。
/sbin/ip addr add 192.168.2.201/24 dev eth0
/sbin/arping -q -c 3 -A 192.168.2.201 -I eth0
查看vip
[root@base-slave2 redis]# ip a | grep inet
inet 127.0.0.1/8 scope host lo
inet6 ::1/128 scope host
inet 192.168.2.35/24 brd 192.168.2.255 scope global noprefixroute eth0
inet 192.168.2.201/24 scope global secondary eth0
下面关闭这台redis服务,看看VIP是否漂移到另一台服务器上
vip漂移到了32上
[root@base-master redis]# ip a | grep inet
inet 127.0.0.1/8 scope host lo
inet6 ::1/128 scope host
inet 192.168.2.32/24 brd 192.168.2.255 scope global noprefixroute eth0
inet 192.168.2.201/24 scope global secondary eth0
通过vip连接redis也可以成功
[root@localhost ~]# redis-cli -h 192.168.2.201
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.2.201:6379> ping
PONG
192.168.2.201:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.2.34,port=6379,state=online,offset=1320728,lag=0
slave1:ip=192.168.2.35,port=6379,state=online,offset=1320728,lag=0
master_replid:d3b972b1e664c0856093deea8d23b7c0bb0f3413
master_replid2:67c6248cb3e6f07e8d8f99d22c6984920e8e16e3
master_repl_offset:1320869
second_repl_offset:1241693
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1231871
repl_backlog_histlen:88999
搭建完成
参考:
https://www.cnblogs.com/linuxk/p/10718153.html
https://www.cnblogs.com/-wenli/p/11379606.html
https://www.cnblogs.com/maybesuch/p/10257374.html