Redis Sentinel(哨兵) 是redis自带的集群管理工具。目前官方推荐使用redis2.8或3.0及以上版本,一个稳定的Sentinel 2已经包括在这些版本中,redis2.6不建议使用。
主要功能
监控(Monitoring)
Sentinel会不断检查redis主服务(master)与从服务(slave)是否正常工作
-
提醒(Notification)
当被监控的某一个redis服务出现故障时,Sentinel会通过api通知管理员或应用程序
-
灾难自动恢复(Automatic failOver)
当主服务出现故障,Sentinel会开始灾难恢复,选出一个从服务升级为主服务继续向提供服务 同时其他的从服务改为监听最新的主服务,当之前的主服务故障恢复后,Sentinel会自动把恢复的服务改成从服务
-
主redis配置提供(Configuration provider)
客户端通过连接Sentinel来获取当前主redis服务的地址,如果主redis服务挂了,Sentinel会自动报告最新的主redis服务地址
简介
Sentinel是一个分布式系统:
多个Sentinel进程相互协作,每一个Sentinel都在自己的配置中运行,Sentinel必须通过配置文件启动,这样做的优势:
- 当已知的主redis不可用时,多个Sentinel会对主redis进行故障检测,减少误判
- 即使个别Sentinel不可用,整个分布式系统还是可以使用
- 通过配置文件保存当前的服务状态,Sentinel重启的时候可以重新加载这些状态
名词解释:
- 主观下线(Subjectively Down, 简称 SDOWN)
单个 Sentinel 实例对服务器做出的下线判断 - 客观下线(Objectively Down, 简称 ODOWN)
多个Sentinel对同一个服务器做出SDOWN判断,并且互相交流之后, 得出的服务器下线判断。
工作原理:
- Sentinel集群通过给定的配置文件发现的master,启动时监控master,同时通过向master发送info来获得所有的slave
- sentinel通过命令连接向被监视的主从服务器发送hello信息(每秒一次),以此来向其他sentinel宣告自己的存在
- sentinel通过订阅接收其他sentinel发送的hello信息,以此来发现监视同一个master的其他sentinel
- sentinel使用ping命令来检测服务的状态,如果在指定的时间内(down-after-milliseconds)没有正确回复,判定SDOWN,触发failover
- failover被触发后,不会马上进行,还需要集群中大多数sentinel授权后才可以进行,即进行failover的sentinel会去获得指定个数的sentinel的授权,成功后进入ODOWN。如在5个sentinel中配置了2,等到2个sentinel认为master死了就执行failover。
- sentinel向选为master的slave发送SLAVEOF NO ONE命令,选择slave的条件是sentinel首先会根据slaves的优先级来进行排序,优先级越小排名越靠前。
-
sentinel被授权后,它将会获得宕掉的master的一份最新配置版本号(config-epoch),当failover执行结束以后,这个版本号将会被用于最新的配置,通过广播形式通知其它sentinel,其它的sentinel则更新对应master的配置。
配置
目录结构
master redis
#编辑/masterRedisPath/redis_master.conf文件
bind 10.0.2.190 #默认为127.0.0.1,通过Sentinel获得redis主服务器地址时会映射成此地址,外部链接将无法连接到redis服务
protected-mode no #默认为yes,即只有本机可以访问,关掉保护模式,可以使外部应用访问该redis, 设置为no后一定要设置redis连接密码
port 6379 #默认端口号,当部署主从redis时,需要设置不同的端口
daemonize yes #守护进程
pidfile "/var/run/redis_6379.pid" #pid文件,redis主从服务器需设置不同pid文件路径
logfile "/home/log/redis_6379.log" #redis日志文件
masterauth utry1234 #主服务器验证密码
requirepass utry1234 #redis连接密码
slave redis
#基本与主redis配置相同,只解释不同部分
#slaveof <master-ip> <master-port> 这个是slave的关键,配置后即可成为master的slave
#即redis会采用异步复制的方式将数据从master热备到slave
#默认下slave是只读的,可以通过配置关闭
#编辑/slaveRedispath/redis_slave.conf
bind 10.0.2.190
protected-mode no
port 6380 #从redis服务器端口
daemonize yes
pidfile "/var/run/redis_6380.pid"
logfile "/home/log/redis_6380.log"
masterauth utry1234
slaveof 10.0.2.190 6379 #设置从属的主redis服务器访问地址,即以这个配置文件启动的redis为slave
requirepass utry1234
Sentinel
#根据官方推荐配置至少3个Sentinel以保证系统稳定工作
#redis安装目录下提供了sentinel.conf的配置示例,在主redis目录下复制该示例3份,分别命名sentinel63791.conf,sentinel63792.conf,sentinel63793.conf
port 63791 #sentinel端口
protected-mode no #sentinel.conf默认是没有这个配置的,需要手动添加
daemonize yes #守护进程
logfile "/home/log/sentinel_63791.log" #运行日志,可以在此查看主从状态
sentinel monitor mymaster 10.0.2.190 6379 2 #配置监控主服务器,mymaster:定义主服务器名, 10.0.2.190:主服务ip 6379:主服务端口 2:设置当有2个sentinel判断master故障后才真正认为master无法继续提供服务,即开始容灾措施
sentinel down-after-milliseconds mymaster 60000 #指定sentinel认定一个服务器断线的毫秒数,即一个sentinel认定服务SDOWN,在这个配置时间内需要获得指定个数的Sentinel判定ODWON,才开始failover
sentinel failover-timeout mymaster 180000 #在触发failover多少秒后任未执行任何failover,则被认为failover失败
sentinel parallel-syncs mymaster 1 #选项指定了在执行故障转移时, 最多可以有多少个从服务器同时对新的主服务器进行同步,这个数字越小, 完成故障转移所需的时间就越长
sentinel auth-pass mymaster utry1234 #主redis服务器验证密码
启动服务
主redis: redis-server /masterRedisPath/to/redis.conf
从redis: redis-server /slaveRedisPath/to/redis.conf
访问redis: redis-cli -h 10.0.2.190 -p 6379 -a utry1234 #-h:ip地址,-p:访问端口,-a:连接密码
进入redis客户端之后,通过info命令查看redis主从状态: info replication
sentinel: redis-sentinel /path/to/sentinel.conf
或 redis-server /path/to/sentinel.conf --sentinel
访问sentinel:与访问redis一样,可以用info命令查看集群状态: info
测试
启动master与slave之后
查看master的状态:role:master,同时显示了slave的信息
查看slave状态:role:slave,同时显示了所属的master redis信息
查看Sentenel状态:status =ok,同时显示了当前的master访问地址,以及slave和sentinel数量
down掉master redis 进程,查看sentinel日志,sentinel自动把slave选举为新的master,同时slave的状态信息role:master
过程解释:
- Sentinel发现master不可用判定主观下线(SDOWN)
- 与集群中其他的Sentinel交流后判定为客观下线(ODWON)
- Sentinel投票选举出一个领头羊Sentienl,由这个领头羊来进行failover
- 领头羊将选出一个slave升级为master,同时修改这个被升级的slave的配置使其成为master的配置
- 将其他的slave配置改成最新master的slave,同时通知其他Sentinel进行修改
- 当之前的master从故障中恢复后,sentinel会自动发现,并采用最新的配置,将这个恢复的redis改成最新master的slave
与Jedis集成
jedis支持Sentinel+redis形式的高可用redis方案
gradle
compile 'redis.clients:jedis:2.6.3'
compile 'org.springframework.data:spring-data-redis:1.6.0.RELEASE'
spring XML configuration
<bean id="sentinelConfig" class="org.springframework.data.redis.connection.RedisSentinelConfiguration">
<property name="master"><!-- 配置master的名字,和Sentinel中配置的master名字一致 -->
<bean class="org.springframework.data.redis.connection.RedisNode">
<property name="name" value="mymaster"></property>
</bean>
</property>
<property name="sentinels"><!-- 配置可用的Sentinel -->
<set>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="10.0.2.190"/>
<constructor-arg name="port" value="63791"/>
</bean>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="10.0.2.190"/>
<constructor-arg name="port" value="63792"/>
</bean>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="10.0.2.190"/>
<constructor-arg name="port" value="63793"/>
</bean>
</set>
</property>
</bean>
<!-- 配置redis连接工厂 -->
<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<constructor-arg ref="sentinelConfig" /><!-- sentinel配置-->
<property name="password" value="utry1234"/><!-- redis连接密码 -->
</bean>
<!-- redis操作模板,在代码中注入这个模板,就可以进行redis的相关操作了 -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory" />
</bean>