Redis主从以及哨兵集群搭建
一、前言
Redis主从同步原理同MySQL的主从原理十分相似,而解决Redis单点故障的哨兵机制(sentinel)又同解决MySQL单点故障的MHA十分相似。因此我们在学习Redis时,可以将学习MySQL的知识迁移,这样一来,有利于我们快速掌握Redis主从机制,Redis哨兵集群的搭建。Redis的Sentinel机制大概是这样的。sentinel即哨兵,作用即放哨。开个玩笑,其实哨兵有三个作用:监控、通知和自动故障转移。哨兵是用来监控Redis的master(主服务器)的,一旦master宕机了,便立刻通知其他slave(从服务器)做好成为master的准备。一旦在自设定的时间内确定master是真的宕机了,就会随机切换一个slave成为master。但是这里会出现一个问题,哨兵(sentinel)的权利是不是太大了?而且万一在监控的时间内出问题的是哨兵自己而不是master,那就会出现误报。因此,我们需要有一个机制限制哨兵的权利。这个机制就是quorum(法定投票机制)机制。我们可以通过投票的方式来决定哨兵的消息是否真实可靠而不是哨兵自己本身宕机了?那既然需要投票,一个哨兵肯定不行,那两个呢?那肯定也不行!假设一台哨兵宕机了,而master是没有宕机的。那这台哨兵会报告master宕机的消息,而另外一台哨兵服务器则不会报告master宕机的消息。那这种情况就很尴尬了,左右为难了。因此我们既然要投票而且必须要有一个正确的可靠消息,那需要的哨兵数必然要大于2个了,因此一般推荐哨兵个数三个以上。
二、实验环境
说明:系统为CentOS7.3。由于是在虚拟机上实验的,这里为了节省资源将三个从节点也配置了Sentinel的功能,当然你也可以将Sentinel独立出来为一个集群。
三、实验配置
1 初始化配置
#node1 /etc/hosts文件修改(其他节点也做类似的修改,保证本机能够基于主机名通信)
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 node1
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 node1
192.168.0.51 node1
192.168.0.52 node2
192.168.0.53 node3
192.168.0.54 node4
#修改hostname(可立即生效)
hostnamectl set-hostname node1
hostnamectl set-hostname node2
hostnamectl set-hostname node3
hostnamectl set-hostname node4
#查看hostname
[root@localhost ~]# hostnamectl
Static hostname: node1
Icon name: computer-vm
Chassis: vm
Machine ID: 3d8bf6a9bfb24fae9bedcb9cfc6c5960
Boot ID: 75905236f9eb4d91ade64f99a690d329
Virtualization: vmware
Operating System: CentOS Linux 7 (Core)
CPE OS Name: cpe:/o:centos:centos:7
Kernel: Linux 3.10.0-514.el7.x86_64
Architecture: x86-64
#注:重新登陆终端,命令提示符就会更改成你修改的hostname
#时间同步(四个节点都要同步)
[root@node1 ~]# ntpdate 172.16.0.1
18 Jul 22:45:00 ntpdate[10418]: step time server 172.16.0.1 offset 0.708020 sec
#另外防火墙规则请自行设置好,selinux确保关闭
2 安装redis,redis主从配置
#下载好redis rpm包
redis-3.2.3-1.el7.x86_64.rpm
#安装redis(4个节点都要执行)
yum install -y redis-3.2.3-1.el7.x86_64.rpm
#将配置文件备份(4个节点都要执行)
cp /etc/redis.conf{,.bak}
#修改配置文件(4个节点都要执行)
vim redis.conf
bind 192.168.0.51 #改为各个节点的IP
#在从节点(node2、node3、node4)开启slave功能
vim /etc/redis.conf
################################# REPLICATION #################################
# slaveof <masterip> <masterport>
slaveof 192.168.0.51 6379
#启动redis-server(4个节点都启动)
redis-server /etc/redis.conf
#查看服务是否启动(演示node2,其他自行测试)
[root@node2 ~]# ss -tln
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 192.168.0.52:6379 *:*
LISTEN 0 128 *:22 *:*
LISTEN 0 100 127.0.0.1:25 *:*
LISTEN 0 128 :::22 :::*
LISTEN 0 100 ::1:25 :::*
#在主机上登陆redis
[root@node1 ~]# redis-cli -h 192.168.0.51
192.168.0.51:6379> KEYS *
(empty list or set)
#设置一对键值,用于同步测试
192.168.0.51:6379> SET test 'amazing'
OK
192.168.0.51:6379> get test
"amazing"
#登陆其他三台从服务器
redis-cli -h 192.168.0.52
redis-cli -h 192.168.0.53
redis-cli -h 192.168.0.54
#三个节点上测试
#node2查看键值对,已经同步了
192.168.0.52:6379> keys *
1) "test"
192.168.0.52:6379> get test
"amazing"
#node3查看键值对,已经同步了
192.168.0.53:6379> keys *
1) "test"
node4查看键值对,已经同步了
192.168.0.54:6379> keys *
1) "test"
由此证明redis主从配置基本实现
#node1上查看主从信息,也可看到主从配置已经实现
192.168.0.51:6379> INFO replication
# Replication
role:master
connected_slaves:3
slave0:ip=192.168.0.52,port=6379,state=online,offset=732,lag=0
slave1:ip=192.168.0.53,port=6379,state=online,offset=732,lag=0
slave2:ip=192.168.0.54,port=6379,state=online,offset=732,lag=0
master_repl_offset:732
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:731
3 sentinel集群实现(哨兵)
接下来在三个从节点上配置sentinel,实现故障转移。
#三个从节点都需要做如下配置
cp /etc/redis-sentinel.conf{,.bak}
vi /etc/redis-sentinel.conf
sentinel monitor mymaster 192.168.0.51 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 18000
#启动服务
redis-sentinel /etc/redis-sentinel.conf
#查看服务是否正常启动
[root@node ~]# ss -tln
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:26379 *:*
LISTEN 0 128 192.168.0.55:6379 *:*
LISTEN 0 128 *:22 *:*
LISTEN 0 100 127.0.0.1:25 *:*
LISTEN 0 128 :::26379 :::*
LISTEN 0 128 :::22 :::*
LISTEN 0 100 ::1:25 :::*
#模拟故障
#杀掉node1 redis进程
[root@node1 ~]# pkill redis
[root@node1 ~]# ss -tln
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:111 *:*
LISTEN 0 128 *:22 *:*
LISTEN 0 100 127.0.0.1:25 *:*
LISTEN 0 128 :::111 :::*
LISTEN 0 128 :::22 :::*
LISTEN 0 100 ::1:25 :::*
#登陆node3,查看信息,发现node3变成master,实现故障转移
[root@node3 ~]# redis-cli -h 192.168.0.53
192.168.0.53:6379> INFO Replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.0.54,port=6379,state=online,offset=23900,lag=0
slave1:ip=192.168.0.52,port=6379,state=online,offset=23900,lag=0
master_repl_offset:24177
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:24176
#再次模拟故障
#杀掉node3 redis
[root@node3 ~]# pkill redis
[root@node3 ~]# ss -tln
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:22 *:*
LISTEN 0 100 127.0.0.1:25 *:*
LISTEN 0 128 :::22 :::*
LISTEN 0 100 ::1:25 :::*
#登陆node4 查看信息,发现node4为master,node2为从,此时为一主一次
[root@node4 ~]# redis-cli -h 192.168.0.54
192.168.0.54:6379> INFO Replication
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.0.52,port=6379,state=online,offset=10508,lag=0
master_repl_offset:10508
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:10507
#启动node1和node3的redis服务,恢复到正常状态
[root@node1 ~]# redis-server /etc/redis.conf
[root@node3 ~]# redis-server /etc/redis.conf
#node3变为主节点,现在为一主三从
[root@node3 ~]# redis-cli -h 192.168.0.53
192.168.0.53:6379> INFO Replication
# Replication
role:master
connected_slaves:3
slave0:ip=192.168.0.51,port=6379,state=online,offset=8008,lag=0
slave1:ip=192.168.0.52,port=6379,state=online,offset=8146,lag=0
slave2:ip=192.168.0.54,port=6379,state=online,offset=7869,lag=1
master_repl_offset:8146
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:8145
(PS:Redis系列第三篇将会介绍Redis的性能优化)