起因:随着项目的进一步推广,数据量的增大,直接访问mysql数据库获取数据所使用的时间越来越长,为解决当前主要矛盾,决定引入redis非关系型数据库作为缓存层,使得数据并不能直接命中数据库,减少访问数据库带来的压力,从而加快运行速度。
1. Redis哨兵机制和实现原理分析
问题:Master挂了,如何保证可用性,实现继续写
现象:slave的数据还有,需要手动把slave升级成master,需要去修改程序的配置了,很不方便,啥时候的挂的?
解决:Redis本身就提供了一个机制-Sentinel哨兵
什么是哨兵
Redis的sentinel机制是用于管理多个redis服务器的,sentinel会执行以下四个任务
- 服务监控:负载监控redis master和slave进程是否正常工作
- 消息通知:master如果挂了,哨兵可以根据你配置的脚本来调用发送通知
- 故障转移:master node挂了,sentinel会从slave里选举一个node成为master,会让剩下的slave follow到新master上并从新master复制数据
- 配置中心:如果故障发生转移了,sentinel可以通知客户端,新的master地址的端口是什么
1.1. 配置哨兵
# redis的安装根目录下,有个sentinel.conf
# 部署三个哨兵节点,同时监控一组redis服务(只有一个节点其实也可以,但风险)
# bind 127.0.0.1 192.168.1.1
# 测试的时候放开访问保护
protected-mode no
port 26379 #默认是26379
daemonize yes
pidfile /var/run/redis-sentinel-26379.pid #pid 集群要区分开
logfile /usr/local/redis-6379/sentinel/redis-sentinel.log #日志,非常重要
dir /usr/local/redis-6379/sentinel #工作空间
# sentinel监控的核心配置
# 最后一个2,quorum,>=2个哨兵主观认为master下线了,master才会被客观下线,才会选一个slave成为master
sentinel monitor icoding-master 127.0.0.1 6379 2
# master访问密码
sentinel auth-pass icoding-master icoding
# sentinel主观认为master挂几秒以上才会触发切换
sentinel down-after-milliseconds icoding-master 3000
# 所有slave同步新master的并行同步数量,如果是1就一个一个同步,在同步过程中slave节点是阻塞的,同步完了才会放开
sentinel parallel-syncs icoding-master 1
# 同一个master节点failover之间的时间间隔
sentinel failover-timeout icoding-master 180000
配置完毕进行启动
redis-sentinel sentinel.conf
# 如果要搭建集群,只需要将刚刚配置的sentinel.conf复制到其他节点即可
哨兵集群部署的约定
- 哨兵集群至少3个节点
- 最好三个节点在不同的物理机器上
- 一组哨兵最好只监控一组主从
1.2. 查看哨兵信息
redis-cli -p 26379 #通过哨兵的端口进入
sentinel master icoding-master
sentinel slaves icoding-master
sentinel sentinels icoding-master #查看哨兵信息
1.3. 哨兵故障转移的原理
1.3.1. 主观宕机和客观宕机
S_DOWN和O_DOWN
- S_DOWN (Subjectively Down) 主观宕机
- 一个哨兵根据配置的主观宕机秒数,认为一个master宕机了,就是主观宕机
- sentinel down-after-milliseconds icoding-master 3000 就是这个配置
- 哨兵ping主机,然后返回超过上面设置的时间就认为主观宕机了
- O_DOWN(Objectively Down) 客观宕机
- 如果quorum数量的哨兵觉得一个master宕机了,就是客观宕机
1.3.2. 哨兵集群是如何自动发现的
刚刚创建哨兵集群的时候并没手动设置之间的关联
image-20200209220147908.png通过pub/sub机制来实现的,每个哨兵都会pub一个sentinel:hello并通过sub来获取和感知有多少个同组redis监控的哨兵
并且信息里会携带host ip runid,并让其他哨兵感知到
1.3.3. slave->master选举算法
会考虑的slave选举的信息
- 和master断开的时长
- slave的优先级:replica-priority 100
- 复制的offset位移程度
- run_id
如果slave和master连接断开超过:down-after-milliseconds icoding-master这个配置的10倍以上绝对不考虑
slave的选举排序顺序
1、按照slave优先级进行排序,replica priority越低,优先级越高
2、如果replica priority级别相同,看offset越靠后(复制的内容多少),优先级越高
3、如果上面两个条件都一样,这个时候看run_id ,run_id字符排序越靠前越优先
先选一个执行主从的sentinel,这个sentinel在根据主从选举算法进行选举
1.3.4. quorum和majority
每次哨兵要做主从切换,首先需要quorum数据的哨兵认为O_DOWN,然后选举一个哨兵来做主从切换,这个哨兵要得到majority数量哨兵的授权,才能正式切换
如果quorum<majority,如果5个哨兵,maj就是3个,qu就是2个
如果quorum>=majority,必须quorum数量的哨兵都授权
1.3.5. configuration epoch
监控的版本号,这个时候所有的哨兵都会记录一套当前的主从关系,这个关系的变更,切换版本号
一个执行哨兵完成了主从切换后,就会通过pub/sub机制来传播给其他哨兵
1.4. 哨兵故障转移的实现
关闭6379的master服务
image-20200209222359461.png
哨兵故障转移的实现方式
依赖于config命令的,我们可能会改成imconfig
# 可以通过这个命令来修改成无redis修改后的config命令
# SENTINEL rename-command mymaster CONFIG IMCONFIG
实现切换的机制
1. 通过config命令修改redis.conf的主从关系
修改自己的sentinel.conf的主机监控命令
2. 在sentinel.conf配置的最下端写入当前主从的版本,供所有哨兵进行使用
sentinel leader-epoch icoding-master 1
sentinel known-replica icoding-master 127.0.0.1 7002
sentinel known-replica icoding-master 127.0.0.1 6379
sentinel known-sentinel icoding-master 127.0.0.1 26379 ce3608694909e996b280e8672750b2bd5522945f
sentinel known-sentinel icoding-master 127.0.0.1 26382 a2f203e003ce891a08580104dc2b49a4f6ae187e
sentinel current-epoch 1
1.5. 哨兵的故障通知机制
# sentinel notification-script <master-name> <script-path>
# 当我们master出现sdown和odown都会触发
sentinel notification-script icoding-master /usr/local/redis/nofity.sh
# sentinel client-reconfig-script mymaster /var/redis/reconfig.sh
# 会带有一些参数:主从切换新旧地址的参数
# <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
sentinel client-reconfig-script icoding-master /usr/local/redis/configer.sh
1.6. 哨兵转移过程中的问题
-
异步复制的时候,master的数据还没有复制给slave,这个时候哨兵切换slave成为master后就会丢失这些数据(新master会把他的数据同步到其他slave:清空其他slave进行同步)
-
脑裂:哨兵的网络和master断开了,但我们master还在运行,这个时候客户端写入旧master的时候就会丢失
old-master<-->client 是连接的,这个时候old-master就没有slave,可以通过以下两个配置来缓解
- min-replicas-to-write 2
- min-replicas-max-lag 10
new-master---slave1/slave2
1.7. 程序如何确保访问有效
如果我们直接连接master还是不能解决故障转移的问题
这个时候就需要连接我们哨兵ip port
spring:
redis:
host: 127.0.0.1
password: icoding
sentinel:
master: icoding-master
nodes: 39.99.199.5:26379,39.99.199.5:26381,39.99.199.5:26382
不要以为每天把功能完成了就行了,这种思想是要不得的,互勉~!
网友评论