基于Sentinel的Redis高可用方案Byyinmingjun本文基于redis-2.8.10和jedis2.4.2版本。背景描述目前,redis的高可用方案一般基于keepalived+RedisMaster/Slave+keepalived事件脚本的模式,依赖keepalived的探测能力,完成Redis的主从实例的切换和配置。这个方式主要有下面的缺点:keepalived是机器级别的HA方案,无法满足大量的对redis的HA需求;keepalivedHA方案不是redis官方的方案,社区的支持力度有限;需机器的访问权限,对脚本和cron做额外的安装部署,有一定的不可控性。Redis从2.8版本开始正式发布Sentinel的功能,使用一个或多个sentinel和Redis的master和slave可以组成一个群集,来检测Redis的master实例是否存活,并在Redismaster实例发生故障时,将Redismaster的slave提升为master,并在老的master重新加入到redissentinel的群集之后,会被重新配置,作为新master的slave。这意味着基于redissentinel的HA群集是能够自我管理的!本文将描述什么是sentinel群集,sentinel群集的配置,以及sentinel群集的验证。redissentinel高可用方案&验证方案描述本文涉及的高可用方案主要面对的场景是如何避免单点故障,基本的保障能力通过sentinel群集和redis的master-slave机制来保证,数据的一致性通过redis的master-slave机制复制参数来调整。基本思路如下:创建redissentinel群集,作为基础服务;动态配置sentinel,动态添加redismaster-slave群集;客户端通过jedis通过其sentinelAPI访问redis群集注:多个redismaster-slave群集共享一个redissentinel群集。Redis群集1Redis群集2Redis群集N客户端Sentinel群方案的核心提供几个基础的sentinel为所有的redissentinel群集服务。在此基础上,需通过测试验证:同一个sentinel对多集群的支持。多群集的redis之间的逻辑隔离。redissentinel进程的资源消耗和群集数量的关系。sentinel的动态配置命令。sentinel对redis主从关系的配置。使用jedis访问redissentinel群集。安装部署指南安装部署sentinel1)从redis官方网站下载最新的redis:wget)解压缩,并编译、测试&安装:tar-xzvfredis-2.8.11.tar.gzcdredis-2.8.11/makemaketestmakeinstall3)创建一个名字为sentinel_26379.conf的空文件,然后使用下面的命令启动sentinel:redis-sentinel./sentinel_26379.conf--port263794)在其它选择为sentinel的机器上,重复上面的步骤安装部署redis实例参考redis的部署文档,创建redis实例。配置redis主从关系由于redis的sentinel群集中的关系是需要支持错误恢复,主从关系由sentinel来维护。因此每个redis的实例启动的时候不要包含主从关系。在初次加入sentinel的时候,通过redis-cli进行配置:redis-cli-hxxx–pxxxxSLAVEOFxxxxxxx注:对于希望设置密码,需预先在配置文件中配置好requirepass和masterauth。同时在sentinel配置好:#sentinelauth-passmaster-namepassword或者通过redis-cli中设置:sentinelsetmaster-nameauth-passpassword添加、删除redis群集有两种方式,一种是通过配置文件,如何配置参考附录的sentinel.conf。这种方式主要是面向预配置的redis群集。另外一种方式使用redis-cli做热配置:127.0.0.1:26381sentinelmonitormymaster172.18.18.20765011OK命令的格式如下:SENTINELMONITORnameipportquorum注:quorum表示发起failover需要的sentinel数量,看sentinel群集的数量决定。从sentinel中删除群集,命令:172.18.18.207:26381sentinelremovemymasterOK查看sentinel信息最简单的是看info:redis-cli-h172.18.18.207-p26379172.18.18.207:26381info#Serverredis_version:2.8.10.....run_id:4b781013a64bfa1f543fd87c51fa4a0dc499513ctcp_port:26381uptime_in_seconds:533532uptime_in_days:6hz:18lru_clock:10563349config_file:/home/ubuntu/sentinel3.conf#Sentinelsentinel_masters:1sentinel_tilt:0sentinel_running_scripts:0sentinel_scripts_queue_length:0master0:name=mymaster,status=odown,address=172.18.18.207:6501,slaves=0,sentinels=2可以使用redis-cli查看sentinel管理的redis群集:redis-cli-h172.18.18.207-p26379172.18.18.207:26381sentinelmasters1)1)name2)mymaster3)ip4)172.18.18.2075)port6)6500...查看一个指定的master有那些slaves:172.18.18.207:26379sentinelslavesmymaster1)1)name2)172.18.18.207:65013)ip4)172.18.18.2075)port6)6501...还可以强制一个redis群集做failover:172.18.18.207:26379sentinelfailovermymasterOK方案的验证综合上面的验证需求,设计测试场景如下。测试准备1)创建5个redissentinel实例2)准备redis实例若干注:参考安装部署sentinel测试1–基本能力验证目标:redissentinel的failover的能力jedissentinel的访问能力sentinel群集的主体数量==sentinel群集数量的一半(含)以上准备工作:创建sentinel的mymaster群集1)准备两个redis实例,并配置master-slave关系,参考配置redis主从关系:2)使用mymaster1作为name,在全部sentinel中添加redis群集,并配置quorum设置为2,参考添加、删除redis群集work--list:1)使用jedis客户端不断读写key值(需写测试程序)2)在读写期间,使用redis-cli向master发送shutdown命令check:检测jedis客户端和sentinel日志,sentinel会在指定的时间内发动failover测试结果:按照down-after-milliseconds配置的默认值,在master停止工作30s后执行了failover,使slave成为master;在failover期间,客户端会收到JedisConnectionException异常;3)启动shutdown的redis,等待10s钟4)使用redis-cli向两个sentinel发送shutdown命令5)再使用redis-cli向新的master发送shutdown命令check:检测jedis客户端和sentinel日志,sentinel会在指定的时间内发动failover测试结果:按照down-after-milliseconds配置的默认值,在master停止工作30s后执行了failover,使slave成为master;在failover期间,客户端会收到JedisConnectionException异常;6)启动shutdown的redis,等待10s钟7)再使用redis-cli向一个sentinel发送shutdown命令(停止了5个sentinel中的3个)8)再使用redis-cli向新的master发送shutdown命令check:检测jedis客户端和sentinel日志,sentinel无法做failover测试结果:无法完成failover;9)启动shutdown的3个sentinel中的一个check:原来挂起的failover会马上执行测试结果:经过down-after-milliseconds配置的时间(默认的30s)之后,sentinel启动failover;10)从这个刚刚启动中的sentinel中去掉mymaster,参考添加、删除redis群集11)再次做shutdown这个sentinel12)再使用redis-cli向新的master发送shutdown命令check:不确定结果。如果sentinel有退出机制,failover能成功;否则,不成功。测试结果:无法完成failover;说明对redis-2.8.10来说,sentinel没有退出redis群集的机制;测试2–多群集支持验证目标:sentinel任意组合的能力sentinel支持多群集的能力sentinel群集的隔离性work--list:1)使用mymaster1作为name,在sentinel中的3个实例中加入redis群集1,quorum设置为12)使用mymaster2作为name,在sentinel的3个实例中加入redis群集2,quorum设置为1。注:sentinel与前面有一个实例的重复度3)在各个sentinel实例上使用sentinel命令查询其master的关系check:重合的sentinel上有两个master测试结果:OK,能查询到两个master:ps:对于sentinelmonitor命令,添加的redis必须是master,否则redis群集的状态会不正确。4)对mymaster1做failovercheck:mymaster1的failoverOK,mymaster2没变化测试结果:OK:5)对mymaster2做failovercheck:mymaster2的failoverOK,mymaster1没变化测试结果:OK:6)分别使用jedissentinel访问mymaster1和mymaster2check:访问正常。测试结果:OK,一起正常。sentinel如果不包含给定的master,jedis会抛异常。测试3–sentinel资源消耗验证目标:验证sentinel没增加一个两节点的redis群集的资源消耗情况work--list:1)创建一个sentinel实例2)创建2000个redis实例,组成1000个master-slave群集3)每次100个,添加redis群集到sentinel,直到全部添加完毕check:sentinel内存的增长;sentinel