Redis主从架构+使用sentinel实现主从架构高可用
一、redis主从架构
(一)复制的工作过程:
主库会基于ping check方式检查从库是否在线,如果在线则直接同步数据文件至从服务端,从服务端也可以主动发送同步请求到主服务端,主库如果是启动了持久化功能时,会不断的同步数据到磁盘上,主库一旦收到从库的同步请求时,主库会将内存中的数据做快照,然后把数据文件同步给从库,从库得到以后是保存在本地文件中(磁盘),而后则把该文件装载到内存中完成数据重建。
1、启动redis slave
2、slave会向master发送同步命令,请求主库上的数据,不论从是第一次连接,还是非第一次连接,master此时都会启动一个后台的子进程将数据快照保存在数据文件中,然后把数据文件发送给slave
3、slave收到数据文件以后会保存到本地,而后把文件重载装入内存
主从工作原理
1. 从库发起同步请求
2. 主库收到请求后执行bgsave保存当前内存里的数据到磁盘
3. 主库将持久化的数据发送给从库的数据目录
4. 从库收到主库的持久化数据之后,先清空自己当前内存中的所有数据
5. 从库将主库发送过来持久化文件加载到自己的内存中。
(二)特点:
1、一个Master可以有多个Slave;
2、支持链式复制(一个slave也可以是其他的slave的slave);
3、Master以非阻塞方式同步数据至slave(master可以同时处理多个slave的读写请求,salve端在同步数据时也可以使用非阻塞方式);
(三)启动复制功能:
1、 在cong12上安装redis
参照上面cong11主机的安装操作。过程略
2、 配置slave的主
[root@cong12 ~]# vim /usr/local/redis/etc/redis.conf
replicaof 192.168.1.11 6379 #指定master IP,端口
masterauth 123456 #指定主redis连接认证密码
3、 重启redis服务
[root@cong12 ~]# redis-cli shutdown
[root@cong12 ~]# redis-server /usr/local/redis/etc/redis.conf
4、 看看主从信息
[root@cong12 ~]# redis-cli -h 192.168.1.12
192.168.1.12:6379> info replication #查看主从信息
注意:如果master使用requirepass开启了认证功能,从服务器要使用masterauth <PASSWORD>来连入服务请求使用此密码进行认证;
5、 测试
在cong11插入数据
[root@cong11 ~]# redis-cli -a 123456
127.0.0.1:6379> set test aa
OK
127.0.0.1:6379> get test
"aa"
1.3.5.2、 在cong12查看同步信息
192.168.1.12:6379> keys *
1) "test"
192.168.1.12:6379> get test
"aa"
二、使用sentinel实现主从架构高可用
redis主从切换技术的方法是:当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工干预,费事费力,还会造成一段时间内服务不可用。这不是一种推荐的方式,更多时候,我们优先考虑哨兵模式。
(一)sentinel的工作过程:
sentinel即可以部署在另外的主机上也可以部署在redis主机上,sentinel既能监控又能提供配置功能,向sentinel指明主redis服务器即可(仅监控主服务器),sentinel可以从主服务中获取主从架构信息,并分辨从节点。sentinel可以监控当前整个主从服务器架构的工作状态,一旦发现master离线的情况,sentinel会从多个从服务器中选择并提升一个从节点成为主节点,当主节点被从节点取代以后,那么IP地址则发生了变化,客户之前连接的主节点IP无法连接,此时可以向sentinel发起查询请求,sentinel会告知客户端新的主节点的IP,所以sentinel是redis在主从架构中实现高可用的解决方案。为了防止sentinel误判和单点故障,sentinel也应该部署为集群,sentinel多个节点同时监控redis主从架构,一旦有一个sentinel节点发现redis的主节点不在线时的情况,sentinel会与其他的sentinel节点协商,看其他的sentinel节点是否也同样发现redis的主节点不在线,如果sentinel的多个点节点都发现redis的主节点都为离线,那么则判定redis主节点为离线状态,以此方式避免误判,同样也避免了单点故障。
(二)sentinel:
1、用于管理多个redis服务实现HA;
2、监控多个redis服务节点
3、自动故障转移
sentinel是一个分布式系统,可以在一个架构中运行多个sentinel进程,多个进程之间使用“流言协议”接收redis主节点是否离线,并使用“投票协议”是否实现故障转移,选择哪一个redis的从服务器成为主服务器
该方案有个缺陷:因为主从实例地址(IP,PORT)是不同的,当故障发生进行主从切换后,应用程序无法知道新地址,在Jedis2.2.2中新增了对Sentinel的支持,应用通过redis.clients.jedis.JedisSentinelPool.getResource()取得的Jedis实例会及时更新到新的主实例地址。
Jedis是Redis官方推荐的Java连接开发工具。要在Java开发中使用好Redis中间件,必须对Jedis熟悉才能写成漂亮的代码。运维人员不下需要关心redis集群连接接,这个是开发人员作的工作。如果要提供统一访问出口。可以使用Twemproxy中间件部署集群。
(三)Redis配置哨兵模式
1、配置reids的主从
Reids可以在一台机器上启动多个进程,即在一台主机上开启3个redis进程,相当于3台redis服务器。也可以在3台不同的服务器上进行搭建redis。
这里配置配置3个哨兵和1主2从的Redis服务器来演示这个过程。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
先配置redis的主从服务器
1、 第1台redis配置(主redis)
第一台就用我们上面配置好的reids(cong11)
[root@cong11 ~]# mkdir /var/log/redis
[root@cong11 ~]# cd /usr/local/redis/etc/
[root@cong11 etc]# vim redis.conf
…………省略部分内容
logfile "/var/log/redis/redis_6379.log"
masterauth 123456 #主从切换需要用到密码,如果你redis设置了密码
我问一下,如果该主机为master,为什么还要设置主从切换密码?
答:答对即明白
重启redis服务:
[root@cong11 ~]# pkill redis-server
[root@cong11 ~]# redis-server /usr/local/redis/etc/redis.conf
查看redis的端口监听
[root@cong11 ~]# netstat -anplt | grep redis
tcp 0 0 192.168.1.11:6379 0.0.0.0:* LISTEN 69582/redis-server
2、 第2台redis配置(从redis)
就用我们上面安装好的redis(cong12)
[root@cong12 ~]# mkdir /var/log/redis #创建日志目录
[root@cong12 ~]# mkdir -p /redis/data #创建第2台数据保存目录
[root@cong12 ~]# vim /usr/local/redis/etc/redis.conf #修改配置文件
………..省略部分内容
bind 127.0.0.1 192.168.1.12
port 6379
requirepass 123456
pidfile /var/run/redis_6379.pid #修改pid文件为redis_6380.pid
logfile "/var/log/redis/redis_6379.log" #修改log文件路径
dir /redis/data #修改RDB目录
replicaof 192.168.1.11 6379 #指定master的IP和端口
masterauth 123456 #指定master登陆密码
重启redis服务:
[root@cong12 ~]# pkill redis-server
[root@cong12 ~]# redis-server /usr/local/redis/etc/redis.conf
查看redis的端口监听:
查看主从信息:
3、 第3台redis配置(从redis)
在cong13主机上安装redis,参考前面redis的安装部分。
[root@cong13 ~]# mkdir -p /redis/data
[root@cong13 ~]# mkdir /var/log/redis
[root@cong13 ~]# cp redis-7.4.1/redis.conf /usr/local/redis/etc/
[root@cong13 ~]# vim /usr/local/redis/etc/redis.conf
………….省略部分内容
daemonize yes
bind 127.0.0.1 192.168.1.13
port 6379
requirepass 123456
pidfile /var/run/redis_6379.pid #修改pid文件为redis_6380.pid
logfile "/var/log/redis/redis_6379.log" #修改log文件路径
dir /redis/data #修改RDB目录
replicaof 192.168.1.11 6379 #指定master的IP和端口
masterauth 123456
重启redis服务:
[root@cong13 ~]# redis-server /usr/local/redis/etc/redis.conf
查看redis的端口监听:
查看主从信息:
在主redis中查看主从信息:
4、 添加开机启动(3台redis)
[root@cong11 ~]# echo "redis-server /usr/local/redis/etc/redis.conf" >> /etc/rc.local
[root@cong12 ~]# echo "redis-server /usr/local/redis/etc/redis.conf" >> /etc/rc.local
[root@cong13 ~]# echo "redis-server /usr/local/redis/etc/redis.conf" >> /etc/rc.local
[root@cong11 ~]# chmod +x /etc/rc.d/rc.local
[root@cong12 ~]# chmod +x /etc/rc.d/rc.local
[root@cong13 ~]# chmod +x /etc/rc.d/rc.local
5、 测试主从
[root@cong11 ~]# redis-cli -p 6379
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> set key1 abc
OK
127.0.0.1:6379> get key1
"abc"
[root@cong12 ~]# redis-cli -p 6379
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> get key1
"abc"
[root@cong13 ~]# redis-cli -p 6379
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> get key1
"abc"
(三) 部署sentinel:
三个sentinel节点的sentinel.conf文件配置一样,如果是在同一个主机上,则需要使用不同的端口号。
1、 生成sentinel配置文件
redis-sentinel可以理解为运行有着特殊代码的redis,redis自身也可以运行sentinel,sentinel也依赖配置文件,在redis解压目录下有一个sentinel.conf文件,copy一份进行修改用于保存sentinel不断收集的状态信息.
[root@cong11 ~]# cd redis-7.4.1
[root@cong11 redis-7.4.1]# cp sentinel.conf /usr/local/redis/etc/
2、 修改sentinel.conf配置文件
配置3个哨兵,每个哨兵的配置都是一样的。在Redis安装目录下有一个sentinel.conf文件,copy一份进行修改。
[root@cong11 ~]# vim /usr/local/redis/etc/sentinel.conf #标红的部分需修改
daemonize yes
bind 0.0.0.0 #添加监控IP,一定要写0.0.0.0,不然主从切换不了
logfile "/var/log/redis/sentinel_26379.log"
sentinel monitor mymaster 192.168.1.11 6379 2 #修改master IP
# sentinel monitor <master-name> <ip> <redis-port> <quorum> //此项可以出现多次,可以监控多组redis主从架构,此项用于监控主节点 <master-name> 自定义的主节点名称,<ip> 主节点的IP地址,<redis-port>主节点的端口号,<quorum>主节点对应的quorum法定数量,是一个大于sentinel数量一半的值,所以sentinel数量尽量为奇数个,如果sentinel有3个,则指定为2即可,如果有4个,不能够指定为2,避免导致集群分裂,注意,<master-name>为集群名称,可以自定义,如果同时监控有多组redis集群时,<master-name>不能相同。
注:最后数字2表示如果有两个sentinel认为master挂了,则这个master即认为不可用;
sentinel auth-pass mymaster 123456 #添加这一行
# sentinel auth-pass <master-name> <password>
# sentinel author-pass定义服务的密码,mymaster是服务名称,123456是Redis服务器密码
sentinel down-after-milliseconds mymaster 30000
#sentinel down-after-milliseconds <master-name> <milliseconds> //默认30秒,sentinel会通过ping来判断master是否存活,如果在30秒内master返回pong给sentinel,则认为master是好的,否则sentinel认为master不可用。
sentinel parallel-syncs mymaster 1
#sentinel parallel-syncs <master-name> <numslaves> //当Sentinel节点集合对主节点故障判定达成一致时,Sentinel领导者节点会做故障转移操作,选出新的主节点,原来的从节点会向新的主节点发起复制操作,限制每次向新的主节点发起复制操作的从节点个数为1
sentinel failover-timeout mymaster 180000
#sentinel failover-timeout <master-name> <milliseconds> //故障转移超时时间,在指定时间没能完成则判定为失败,单位为毫秒(默认为180秒)
注:
Redis Sentinel中的身份验证
当一个master配置为需要密码才能连接时,客户端和slave在连接时都需要提供密码;
master通过requirepass设置自身的密码,不提供密码无法连接到这个master;
slave通过masterauth来设置访问master时的密码;
但是当使用了sentinel时,由于一个master可能会变成一个slave,一个slave也可能会变成master,所以需要同时设置上述两个配置项。
将cong11上配置好的sentinel.conf文件拷贝给cong12、cong13。
[root@cong11 ~]# cd /usr/local/redis/etc/
[root@cong11 etc]# scp sentinel.conf root@192.168.1.12:/usr/local/redis/etc/
[root@cong11 etc]# scp sentinel.conf root@192.168.1.13:/usr/local/redis/etc/
3、 启动方式:
sentinel节点有两种启动方法:
# redis-sentinel /usr/local/redis/etc/sentinel.conf
或者:
# redis-server /usr/local/redis/etc/sentinel.conf --sentinel
注意启动的顺序。首先是主机的Redis服务进程,然后启动从机的服务进程,最后启动3个哨兵的服务进程。
[root@cong11 etc]# redis-sentinel /usr/local/redis/etc/sentinel.conf
[root@cong12 ~]# redis-sentinel /usr/local/redis/etc/sentinel.conf
[root@cong13 ~]# redis-sentinel /usr/local/redis/etc/sentinel.conf
添加开机启动:
[root@cong11 ~]#echo "redis-sentinel /usr/local/redis/etc/sentinel.conf" >> /etc/rc.local
[root@cong12 ~]#echo "redis-sentinel /usr/local/redis/etc/sentinel.conf" >> /etc/rc.local
[root@cong13 ~]#echo "redis-sentinel /usr/local/redis/etc/sentinel.conf" >> /etc/rc.local
查看端口监听:
Cong12和cong13也一样。
4、 检查整个集群的状态:
[root@cong11 etc]# redis-cli -h 192.168.1.11 -p 26379
192.168.1.11:26379> info sentinel #看到如下信息说明配置成功
# 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=192.168.1.11:6379,slaves=2,sentinels=3
检查整个集群的状态
192.168.1.11:26379> client list
id=3 addr=192.168.1.12:35149 fd=13 name=sentinel-bbded0b7-cmd age=416 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=ping
id=4 addr=192.168.1.13:37022 fd=15 name=sentinel-31d3685a-cmd age=408 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=ping
id=5 addr=192.168.1.11:49514 fd=17 name= age=101 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=32742 obl=0 oll=0 omem=0 events=r cmd=client
注:当我们启动主从节点和sentinel节点后,sentinel.conf配置文件会自动添加或修改参数
5、 测试:
测试自动failover
可以通过跟踪sentinel的日志文件查看failover切换
1) 关闭master
[root@cong11 ~]# ps -ef | grep redis
[root@cong11 ~]# kill -9 70043
2) 查看主从状态
[root@cong11 ~]# redis-cli -h 192.168.1.11 -p 26379
192.168.1.11:26379> info sentinel
# 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=192.168.1.13:6379,slaves=2,sentinels=3
或
[root@cong11 ~]# redis-cli -h 192.168.1.11 -p 26379
192.168.1.11:26379> sentinel masters
1) 1) "name"
2) "mymaster"
3) "ip"
4) "192.168.1.13"
5) "port"
6) "6379"
………….
192.168.1.11:26379> sentinel slaves mymaster
1) 1) "name"
2) "192.168.1.11:6379"
3) "ip"
4) "192.168.1.11"
5) "port"
6) "6379"
7) "runid"
8) "4e28d6c4515dd61ed296ece6e7450827bc6d2b16"
9) "flags"
10) "slave"
………….
2) 1) "name"
2) "192.168.1.12:6379"
3) "ip"
4) "192.168.1.12"
5) "port"
6) "6379"
7) "runid"
8) "e16264a30605fc49f8edc1c2b37bffee2a6b7ce4"
9) "flags"
10) "slave"
3) 启动主服务器
重启修复好的旧master之后,会自动成为新master的从库
[root@cong11 etc]# redis-server /usr/local/redis/etc/redis.conf
4) 查看主从状态
[root@cong11 etc]# redis-cli -h 192.168.1.11 -p 6379
192.168.1.11:6381> auth 123456
OK
192.168.1.11:6381> info replication
在新的主redis上查看主从信息:
[root@cong13 ~]# redis-cli -p 6379
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> info replication
由以上测试可见,主的故障离线后,sentinel重新选了其一个从reids成为了新的主节点,在原来的主节点重新上线后,仍然不会恢复为主节点。
总结:
Failover过程分析:
sentinel节点会定期通过ping检测redis的master是否存活,一旦master crash,
首先sentinel自己会主观认为master crash,然后三个sentinel之间彼此通信,只要有两个sentinel节点认为master crash,则客观认为master crash,
接着三个sentinel节点会投票,得到两票的一个sentinel会去执行failover,
最后master 30s之内没有响应sentinel才会真正的failover;
一旦挂掉的旧master修复,重新启动后,会作为新master的从库存在;