玩转 Redis 集群之 Sentinel

Redis做为内存数据库,须要具有高可用的特色,否则若是服务器宕机,还在内存里的数据就会丢失。咱们最经常使用的高可用方法就是搭建集群,master机器挂了,可让slave机器顶上,继续提供服务。可是Redis集群是不会自动进行主从切换的,也就是说,若是主节点很是不争气的在凌晨3点挂了,那么运维同窗就要立刻起床,把从节点改为主节点,这样的操做是很是繁琐低效的。为此,Redis官方提供了一种解决方案:Redis Sentinelredis

简介sql

Redis Sentinel集群一般由3到5个节点组成,若是个别节点挂了,集群还能够正常运做。它负责监控Redis集群的健康状况。若是主节点挂掉,Sentinel集群会经过投票选择一个新的主节点。当原来的主节点恢复时,它会被当作新的主节点的从节点从新加入Redis集群。数据库

基本原理服务器

Sentinel集群经过指定的配置文件发现master,对其进行监控,而且会发送info指令获取master的从节点信息。Sentinel集群中的节点经过向其监控的主从节点发送hello信息(包含Sentinel自己的ip、端口和id等内容)来向其余Sentinel宣告本身的存在。架构

Sentinel集群经过订阅链接来接收其余Sentinel的hello信息。并发

Sentinel集群经过ping命令来检查监控的实例状态,若是在指定时间内没有返回,则认为该实例下线。运维

Sentinel触发failover主从切换后,并不会立刻进行,只有指定(quorum)Sentinel受权后,master节点被标记为ODOWN状态。这时才真正开始投票选择新的master。socket

Sentinel选择新的master的原则是:首先判断优先级,选择优先级较小的;若是优先级相同,查看复制下标,选择复制数据较多的;若是复制下标也相同,就选择进程ID较小的。分布式

Sentinel被受权后,它将会得到宕掉的master的一份最新配置版本号(config-epoch),当failover执行结束之后,这个版本号将会被用于最新的配置,经过广播形式通知其它Sentinel,其它的Sentinel则更新对应master的配置。高并发

基本使用

咱们以Python为例,简单说明一下在客户端如何使用Sentinel

1from redis.sentinel import Sentinel
 2
 3if __name__ == '__main__':
 4    sentinel = Sentinel(['localhost', 26379], socket_timeout=0.1)
 5    print(sentinel.discover_master('mymaster'))
 6    print(sentinel.discover_slaves('mymaster'))
 7    master = sentinel.master_for('mymaster', socket_timeout=0.1)
 8    slave = sentinel.slave_for('mymaster', socket_timeout=0.1)
 9    master.set('follow', 'Jackeyzhe2018')
10    follow = slave.get('follow')
11    print(follow)

master_for和slave_for方法会从链接池中拿出一个链接来使用,若是从地址有多个,则会采用轮询的方法。

当redis发生了主从切换时,客户端如何知道地址已经变动了呢?咱们从redis-py的源码里找一找答案。

 

 

 

 

 

 

 

 

 

 

能够看到,redis在建立一个新的链接时,会调用get_master_address方法来获取主节点地址。get_master_address方法中,客户端先查询主节点地址,而后与内存中的地址进行比较。若是不一致,则会断开链接,而后使用新的地址从新进行链接。

若是主节点没有挂,而Sentinel主动进行了主从切换,对于这种状况redis-py也作了处理。就是捕获一个ReadOnlyError的异常,而后断开链接,后续指令都须要从新进行链接了。固然,若是没有修改性指令,那么链接就不会切换,不过数据也不会被破坏,因此影响不大。

动手搭建

关于Sentinel的工做原理和使用方法咱们已经有了大概的认识,为了加深理解,咱们来本身动手搭建一套Sentinel集群。

首先搭建咱们我须要的redis集群环境

安装好redis后,将redis目录下的配置文件redis.conf复制3份。分别命名为redis6379.conf,redis6380.conf,redis6381.conf。

在redis6381.conf文件中修改如下几项

1bind 127.0.0.1
2port 6381
3logfile "6381.log"
4dbfilename "dump-6381.rdb"

在redis6379.conf中修改

1bind 127.0.0.1
2port 6379
3logfile "6379.log"
4dbfilename "dump-6379.rdb"
5slaveof 127.0.0.1 6381

redis6380.conf的修改参照redis6379.conf。修改完成后,分别启动三个实例。就搭建好了咱们想要的redis主从环境了。

 

 

 

 

 

咱们链接上master节点,能够看到它的主从配置信息

 

 

 

 

 

接着,咱们来配置Sentinel集群。这里咱们一样配置三个实例。复制3份sentinel.conf文件,分别命名为sentinel-26379.conf,sentinel-26380.conf和sentinel-26381.conf。

sentinel-26379.conf文件中编辑如下内容

1port 26379  
2daemonize yes  
3logfile "26379.log"  
4dir /home/xxx/redis/data  
5sentinel monitor mymaster 127.0.0.1 6381 2
6sentinel down-after-milliseconds mymaster 30000  
7sentinel parallel-syncs mymaster 1  
8sentinel failover-timeout mymaster 180000

sentinel-26380.conf和sentinel-26381.conf的内容与上述相似。配置好后,咱们使用命令redis-sentinel来启动3个sentinel实例。

 

 

 

 

 

此时,咱们用redis-cli命令链接26379的实例,查看sentinel的信息。

 

 

 

 

 

发现它已经开始监控咱们的3个redis节点了。这时咱们的整个集群就部署好了,接下来测试一下。

kill掉master节点,查看sentinel的日志,会发现sentinel已经按照咱们前面说的步骤选择了新的master。

 

此时再来看sentinel信息。

此时,6380已经成了新的master。

恭喜你,之后都不须要在凌晨起床切换Redis主从实例了。

欢迎工做一到五年的Java工程师朋友们加入Java架构开发: 855835163 群内提供免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)合理利用本身每一分每一秒的时间来学习提高本身,不要再用"没有时间“来掩饰本身思想上的懒惰!趁年轻,使劲拼,给将来的本身一个交代!

相关文章
相关标签/搜索