本篇博客会简单的介绍Redis的Sentinel相关的原理,同时也会在最后的文章给出硬核的实战教程,让你在了解原理以后,可以实际上手的体验整个过程。redis
以前的文章聊到了Redis的主从复制,聊到了其相关的原理和缺点,具体的建议能够看看我以前写的文章Redis的主从复制。docker
总的来讲,为了知足Redis在真正复杂的生产环境的高可用,仅仅是用主从复制是明显不够的。例如,当master节点宕机了以后,进行主从切换的时候,咱们须要人工的去作failover。bash
同时在流量方面,主从架构只能经过增长slave节点来扩展读请求,写能力因为受到master单节点的资源限制是没法进行扩展的。服务器
这也是为何咱们须要引入Sentinel。微信
Sentinel其大体的功能以下图。网络
Sentinel是Redis高可用的解决方案之一,自己也是分布式的架构,包含了多个Sentinel节点和多个Redis节点。而每一个Sentinel节点会对Redis节点和其他的Sentinel节点进行监控。数据结构
当其发现某个节点不可达时,若是是master节点就会与其他的Sentinel节点协商。当大多数的Sentinel节点都认为master不可达时,就会选出一个Sentinel节点对master执行故障转移,并通知Redis的调用方相关的变动。架构
相对于主从下的手动故障转移,Sentinel的故障转移是全自动的,无需人工介入。tcp
666,那我怎么知道知足它自身的高可用须要部署多少个Sentinel节点?分布式
由于Sentinel自己也是分布式的,因此也须要部署多实例来保证自身集群的高可用,可是这个数量是有个最低的要求,最低须要3个。
我去,你说3个就3个?我今天恰恰就只部署2个
你别杠...等我说了为何就必需要3个...
由于哨兵执行故障转移须要大部分的哨兵都赞成才行,若是只有两个哨兵实例,正常运做还好,就像这样。
若是哨兵所在的那台机器因为机房断电啊,光纤被挖啊等极端状况整个挂掉了,那么另外一台哨兵即便发现了master故障以后想要执行故障转移,可是它没法获得任何其他哨兵节点的赞成,此时也永远没法执行故障转移,那Sentinel岂不是成了一个摆设?
因此咱们须要至少3个节点,来保证Sentinel集群自身的高可用。固然,这三个Sentinel节点确定都推荐部署到不一样的机器上,若是全部的Sentinel节点都部署到了同一台机器上,那当这台机器挂了,整个Sentinel也就不复存在了。
大部分?大哥这但是要上生产环境,大部分这个数量未免也太敷衍了,咱就不能专业一点?
前面提到的大部分
哨兵赞成涉及到两个参数,一个叫quorum
,若是Sentinel集群有quorum
个哨兵认为master宕机了,就客观的认为master宕机了。另外一个叫majority
...
等等等等,不是已经有了一个叫什么quorum的吗?为何还须要这个majority?
你能不能等我把话说完...
quorum
刚刚讲过了,其做用是判断master是否处于宕机的状态,仅仅是一个判断做用。而咱们在实际的生产中,不是说只判断master宕机就完了, 咱们不还得执行故障转移,让集群正常工做吗?
同理,当哨兵集群开始进行故障转移时,若是有majority
个哨兵赞成进行故障转移,才可以最终选出一个哨兵节点,执行故障转移操做。
你刚刚是否是提到了客观宕机?笑死,难不成还有主观宕机这一说?
Sentinel中认为一个节点挂了有两种类型:
当一个Sentinel节点与其监控的Redis节点A进行通讯时,发现链接不上,此时这个哨兵节点就会主观的认为这个Redis数据A节点sdown了。为何是主观?咱们得先知道什么叫主观
未经分析推算,下结论、决策和行为反应,暂时不能与其余不一样见解的对象仔细商讨,称为主观。
简单来讲,由于有可能只是当前的Sentinel节点和这个A节点的网络通讯有问题,其他的Sentinel节点仍然能够和A正常的通讯。
这也是为何咱们须要引入odown,当大于等于了quorum个Sentinel节点认为某个节点宕机了,咱们就客观的认为这个节点宕机了。
当Sentinel集群客观的认为master宕机,就会从全部的Sentinel节点中,选出一个Sentinel节点,来最终执行master的故障转移。
那这个故障转移具体要执行些什么操做呢?咱们经过一个图来看一下。
通知调用的客户端master发生了变化
通知其他的原slave节点,去复制Sentinel选举出来的新的master节点
若是此时原来的master又从新恢复了,Sentinel也会让其去复制新的master节点。成为一个新的slave节点。
硬核教程旨在用最快速的方法,让你在本地体验Redis主从架构和Sentinel集群的搭建,并体验整个故障转移的过程。
首先须要准备一个目录,而后分别创建两个子目录。以下。
$ tree . . ├── redis │ └── docker-compose.yml └── sentinel ├── docker-compose.yml ├── sentinel1.conf ├── sentinel2.conf └── sentinel3.conf 2 directories, 5 files
redis目录下的docker-compose.yml
内容以下。
version: '3' services: master: image: redis container_name: redis-master ports: - 6380:6379 slave1: image: redis container_name: redis-slave-1 ports: - 6381:6379 command: redis-server --slaveof redis-master 6379 slave2: image: redis container_name: redis-slave-2 ports: - 6382:6379 command: redis-server --slaveof redis-master 6379
以上的命令,简单解释一下slaveof
就是让两个slave节点去复制container_name为redis-master的节点,这样就组成了一个简单的3个节点的主从架构
而后用命令行进入当前目录,直接敲命令docker-compose up
便可,剩下的事情交给docker-compose去作就好,它会把咱们所须要的节点所有启动起来。
此时咱们还须要拿到刚刚咱们启动的master节点的IP,简要步骤以下:
经过docker ps
找到对应的master节点的containerID
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 9f682c199e9b redis "docker-entrypoint.s…" 3 seconds ago Up 2 seconds 0.0.0.0:6381->6379/tcp redis-slave-1 2572ab587558 redis "docker-entrypoint.s…" 3 seconds ago Up 2 seconds 0.0.0.0:6382->6379/tcp redis-slave-2 f70a9d9809bc redis "docker-entrypoint.s…" 3 seconds ago Up 2 seconds 0.0.0.0:6380->6379/tcp redis-master
也就是f70a9d9809bc
。
经过docker inspect f70a9d9809bc
,拿到对应容器的IP,在NetworkSettings -> Networks -> IPAddress字段。
而后把这个值给记录下来,此处个人值为172.28.0.3
。
sentinel目录下的docker-compose.yml
内容以下。
version: '3' services: sentinel1: image: redis container_name: redis-sentinel-1 ports: - 26379:26379 command: redis-sentinel /usr/local/etc/redis/sentinel.conf volumes: - ./sentinel1.conf:/usr/local/etc/redis/sentinel.conf sentinel2: image: redis container_name: redis-sentinel-2 ports: - 26380:26379 command: redis-sentinel /usr/local/etc/redis/sentinel.conf volumes: - ./sentinel2.conf:/usr/local/etc/redis/sentinel.conf sentinel3: image: redis container_name: redis-sentinel-3 ports: - 26381:26379 command: redis-sentinel /usr/local/etc/redis/sentinel.conf volumes: - ./sentinel3.conf:/usr/local/etc/redis/sentinel.conf networks: default: external: name: redis_default
一样在这里解释一下命令
redis-sentinel 命令让 redis 以 sentinel 的模式启动,本质上就是一个运行在特殊模式的 redis 服务器。
和 redis-server 的区别在于,他们分别载入了不一样的命令表,sentinel 中没法执行各类redis中特有的 set get操做。
创建三份如出一辙的文件,分别命名为sentinel1.conf、sentinel2.conf和sentinel3.conf。其内容以下:
port 26379 dir "/tmp" sentinel deny-scripts-reconfig yes sentinel monitor mymaster 172.28.0.3 6379 2 sentinel config-epoch mymaster 1 sentinel leader-epoch mymaster 1
能够看到,咱们对于sentinel的配置文件中,sentinel monitor mymaster 172.28.0.3 6379 2
表示让它去监听名为mymaster
的master节点,注意此处的IP必定要是你本身master节点的IP,而后最后面的2
就是咱们以前提到的quorum
。
而后命令行进入名为sentinel的目录下,敲docker-compose up
便可。至此,Sentinel集群便启动了起来。
而后咱们须要手动模拟master挂掉,来验证咱们搭建的Sentinel集群是否能够正常的执行故障转移。
命令行进入名为redis的目录下,敲入以下命令。
docker-compose pause master
此时就会将master容器给暂停运行,让咱们等待10秒以后,就能够看到sentinel这边输出了以下的日志。
redis-sentinel-2 | 1:X 07 Dec 2020 01:58:05.459 # +sdown master mymaster 172.28.0.3 6379 ...... ...... ...... redis-sentinel-1 | 1:X 07 Dec 2020 01:58:06.932 # +switch-master mymaster 172.28.0.3 6379 172.28.0.2 6379
得得得,你干什么就甩一堆日志文件上来?凑字数?你这样鬼能看懂?
的确,光从日志文件一行一行的看,就算是我本身过两周再来看,也是一脸懵逼。日志文件完整了描述了整个Sentinel集群从开始执行故障转移到最终执行完成的全部细节,可是在这里直接放出来不方便你们的理解。
因此为了让你们可以更加直观的了解这个过程,我简单的把过程抽象了成了一张图,你们看图结合日志,应该可以更容易理解。
里面关键的步骤步骤的相关解释我也一并放入了图片中。
最终的结果就是,master已经从咱们最开始的172.28.0.3
切换到了172.28.0.2
,后者则是原来的slave节点之一。此时咱们也能够链接到172.28.0.2
这个容器里去,经过命令来看一下其如今的状况。
role:master connected_slaves:1 slave0:ip=172.28.0.4,port=6379,state=online,offset=18952,lag=0 master_replid:f0bf5d1c843ec3ab005c5ac2b864f7ffdc6a8217 master_replid2:72c43e1f9c05d4b08bea6bf9b2549997587e261c master_repl_offset:18952 second_repl_offset:16351 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:18952
能够看到,如今的172.28.0.2
这个节点的角色已经变成了master,与其相链接的slave节点只有1个,由于如今的原master尚未启动起来,总共存活的只有2个实例。
接下来咱们模拟原master从新启动,来看一下会发什么什么。
仍是经过命令行进入到名为redis的本地目录,经过docker-compose unpause master
来模拟原master故障恢复以后的上线。一样咱们链接到原master的机器上去。
$ docker exec -it f70a9d9809bc1e924a5be0135888067ad3eb16552f9eaf82495e4c956b456cd9 /bin/sh; exit # redis-cli 127.0.0.1:6379> info replication # Replication role:slave master_host:172.28.0.2 master_port:6379 master_link_status:up ......
master断线重连以后,角色也变成了新的master(也就是172.28.0.2
这个节点)的一个slave。
而后咱们也能够经过再看一下新master节点的replication状况做证。
# Replication role:master connected_slaves:2 slave0:ip=172.28.0.4,port=6379,state=online,offset=179800,lag=0 slave1:ip=172.28.0.3,port=6379,state=online,offset=179800,lag=1 ......
原master短线重连以后,其connected_slaves变成了2,且原master172.28.0.3
被清晰的标注为了slave1,一样与咱们开篇和图中所讲的原理相符合。
好了,以上就是本篇博客的所有内容
欢迎微信关注「SH的全栈笔记」,查看更多相关的文章
往期文章