一种Redis主从分片集群高可用方法技术

技术编号:23851246 阅读:8 留言:0更新日期:2020-04-18 08:45
本发明专利技术公开了一种Redis主从分片集群高可用方法,基于Redis Sentinel技术实现及时监控集群分片工作状态,主要对Redis Sentinel的监控通知进行监听,及时更新及维护redis连接信息,以实现对应用redis连接池的维护。本发明专利技术在redis分片集群发生主从切换行为时,能够及时更新分片工作状态,更新redis节点状态,保证应用能够正常操作redis。

A high availability method of redis master-slave cluster

【技术实现步骤摘要】
一种Redis主从分片集群高可用方法
本专利技术涉及一种集群高可用方法,特别是一种Redis主从分片集群高可用方法。
技术介绍
随着业务系统的壮大及网站流量的提升,访问数据库的频率剧增,为了在大流量访问下提供稳定的业务,现在大部分的解决方案就是在数据库层之上的各级使用多级的no-sql像redis等来为数据库提供缓冲,同时随着热点数据量的不断增多,单一Redis实例已经不能满足需求,这时就需要采用分片技术,将多个Redis(集群)作为缓存数据库。RedisSentinel是Redis官方提供的集群管理工具,能持续监控Redis的主从实例的工作状态;当被监控的Redis实例出问题时,通知系统管理员或其他程序;如果主实例无法正常工作,Sentinel将把一个从实例提升为主实例,其他的从实例将会被重新配置到新的主实例,且应用程序会得到一个更换新地址的通知。但是在redis分片集群环境下,Jedis并没有提供基于Sentinel的ShardedJedisPool,也就是说在N个redis分片中,如果其中一个分片发生主从切换,应用所使用的ShardedJedisPool无法获得通知,所有对那个分片的操作将会失败。因此如何及时感知所有分片主从切换行为,进行连接池重建是我们需要实际面对的问题。
技术实现思路
本专利技术所要解决的技术问题是提供一种Redis主从分片集群高可用方法。为解决上述技术问题,本专利技术所采用的技术方案是:一种Redis主从分片集群高可用方法,其特征在于包含以下步骤:步骤一:编写分片主从Jedis类;步骤二:创建对Sentinel通知的监听线程;步骤三:创建、加载连接池。进一步地,所述步骤一具体为1.1继承Sharded<Jedis,JedisShardInfo>编写主从Jedis类MasterSlaveJedis,将主节点信息以Jedis提供的JedisShardInfo对象形式存储,将从节点信息以List<JedisShardInfo>对象形式存储,利用主节点的Jedis操作实例重写Jedis的put、get方法,利用Jedis中Sharded类提供的getShard方法编写opsForSlave方法以获取从节点Jedis操作实例;1.2继承Sharded<MasterSlaveJedis,MasterSlaveJedisShardInfo>编写分片主从Jedis类ShardedMasterSlaveJedis,调用Jedis中Sharded类提供的getShard方法,根据缓存数据的Key值获取对应分片的主从节点MasterSlaveJedis操作实例,使用1.1中重写的方法实现redis客户端常用操作,同时编写getFromAvailableSlave方法,利用获取到的MasterSlaveJedis操作实例调用MasterSlaveJedis类的opsForSlave方法获取对应分片的从节点操作实例,实现读取缓存数据时优先从从节点获取数据,以此实现读写分离。进一步地,所述1.1中编写的主从Jedis类MasterSlaveJedis具体为publicJedisopsForSlave(String...slaveHolder){Stringholder=null;if(slaveHolder==null||slaveHolder.length==0){holder=String.valueOf(System.currentTimeMillis());}else{holder=slaveHolder[0];if(holder==null||holder.trim().equals("")){holder=String.valueOf(System.currentTimeMillis());}}returngetShard(holder);}。进一步地,所述1.2中编写分片主从Jedis类ShardedMasterSlaveJedis具体为publicStringgetFromAvailableSlave(Stringkey){MasterSlaveJedisj=getShard(key);List<JedisShardInfo>salves=j.slaveShards;logger.info(String.format("master-info:%s",j.connectionDesc));if(salves!=null&&salves.size()>0){returnj.opsForSlave().get(key);}returnj.get(key);}publicbyte[]getFromAvailableSlave(byte[]key){MasterSlaveJedisj=getShard(key);List<JedisShardInfo>salves=j.slaveShards;logger.info(String.format("master-info:%s",j.connectionDesc));if(salves!=null&&salves.size()>0){returnj.opsForSlave().get(key);}returnj.get(key);}。进一步地,所述步骤二具体为2.1使用Jedis的订阅Subscribe功能,对"+switch-master"、"+sdown"、"-sdown"、"+slave"的事件消息进行监听;2.2实现Jedis中JedisPubSub类的onMessage方法,取得订阅的消息后重新获取所有分片主从节点信息,根据配置的mater名字通过Jedis提供的sentinelGetMasterAddrByName方法获取主节点的IP地址及端口、通过Jedis提供的sentinelSlaves方法获取从节点的IP地址及端口,以此重新加载连接池。进一步地,所述步骤二采用ShardedMasterSlaveListener哨兵监听线程订阅Subscribe功能实现onMessage,具体为sentinelJedis=newJedis(host,port);try{sentinelJedis.subscribe(newJedisPubSub(){publicvoidonMessage(Stringchannel,Stringmessage){logger.info("Sentinel{}published:{}{}",host+":"+port,channel,message);...

【技术保护点】
1.一种Redis主从分片集群高可用方法,其特征在于包含以下步骤:/n步骤一:编写分片主从Jedis类;/n步骤二:创建对Sentinel通知的监听线程;/n步骤三:创建、加载连接池。/n

【技术特征摘要】
1.一种Redis主从分片集群高可用方法,其特征在于包含以下步骤:
步骤一:编写分片主从Jedis类;
步骤二:创建对Sentinel通知的监听线程;
步骤三:创建、加载连接池。


2.按照权利要求1所述的一种Redis主从分片集群高可用方法,其特征在于:所述步骤一具体为
1.1继承Sharded<Jedis,JedisShardInfo>编写主从Jedis类MasterSlaveJedis,将主节点信息以Jedis提供的JedisShardInfo对象形式存储,将从节点信息以List<JedisShardInfo>对象形式存储,利用主节点的Jedis操作实例重写Jedis的put、get方法,利用Jedis中Sharded类提供的getShard方法编写opsForSlave方法以获取从节点Jedis操作实例;
1.2继承Sharded<MasterSlaveJedis,MasterSlaveJedisShardInfo>编写分片主从Jedis类ShardedMasterSlaveJedis,调用Jedis中Sharded类提供的getShard方法,根据缓存数据的Key值获取对应分片的主从节点MasterSlaveJedis操作实例,使用1.1中重写的方法实现redis客户端常用操作,同时编写getFromAvailableSlave方法,利用获取到的MasterSlaveJedis操作实例调用MasterSlaveJedis类的opsForSlave方法获取对应分片的从节点操作实例,实现读取缓存数据时优先从从节点获取数据,以此实现读写分离。


3.按照权利要求2所述的一种Redis主从分片集群高可用方法,其特征在于:所述1.1中编写的主从Jedis类MasterSlaveJedis具体为
publicJedisopsForSlave(String...slaveHolder){
Stringholder=null;
if(slaveHolder==null||slaveHolder.length==0){
holder=String.valueOf(System.currentTimeMillis());
}else{
holder=slaveHolder[0];
if(holder==null||holder.trim().equals("")){
holder=String.valueOf(System.currentTimeMillis());
}
}
returngetShard(holder);
}。


4.按照权利要求2所述的一种Redis主从分片集群高可用方法,其特征在于:所述1.2中编写分片主从Jedis类ShardedMasterSlaveJedis具体为
publicStringgetFromAvailableSlave(Stringkey){
MasterSlaveJedisj=getShard(key);
List<JedisShardInfo>salves=j.slaveShards;
logger.info(String.format("master-info:%s",j.connectionDesc));
if(salves!=null&&salves.size()>0){
returnj.opsForSlave().get(key);
}
returnj.get(key);
}
publicbyte[]getFromAvailableSlave(byte[]key){
MasterSlaveJedisj=getShard(key);
List<JedisShardInfo>salves=j.slaveShards;
logger.info(String.format("master-info:%s",j.connectionDesc));
if(salves!=null&&salves.size()>0){
returnj.opsForSlave().get(key);
}
returnj.get(key);
}。


5.按照权利要求1所述的一种Redis主从分片集群高可用方法,其特征在于:所述步骤二具体为
2.1使用Jedis的订阅Subscribe功能,对"+switch-master"、"+sdown"、"-sdown"、"+slave"的事件消息进行监听;
2.2实现Jedis中JedisPubSub类的onMessage方法,取得订阅的消息后重新获取所有分片主从节点信息,根据配置的mater名字通过Jedis提供的sentinelGetMasterAddrByName方法获取主节点的IP地址及端口、通过Jedis提供的sentinelSlaves方法获取从节点的IP地址及端口,以此重新加载连接池。


6.按照权利要求5所述的一种Redis主从分片集群高可用方法,其特征在于:所述步骤二采用ShardedMasterSlaveListener哨兵监听线程订阅Subscribe功能实现onMessage,具体为
sentinelJedis=newJedis(host,port);
try{
sentinelJedis.subscribe(newJedisPubSub(){
publicvoidonMessage(Stringchannel,Stringmessage){
logger.info("Sentinel{}published:{}{}",host+":"+port,channel,message);
if("+sdown".equals(channel)){//节点下线
String[]messages=message.split("");
if(messages.length==8){
if("slave".equals(messages[0])){
if(masterNames.contains(messages[5])){
StringslaveIp=messages[2];
StringslavePort=messages[3];
StringmasterIp=messages[6];
StringmasterPort=messages[7];
logger.info("Foundunavailableredisslave[{}]formaster[{}@{}]",slaveIp+":"+slavePort,messages[5],masterIp+":"+masterPort);
initSentinelPool();
}else{
logger.error("Ignoringmessageon+sdownformastername{},butourmasternameis{}!",messages[5],masterNames);
}
}else{
logger.error("InvalidmessagereceivedonSentinel{}onchannel+sdown:{}",host+":"+port,message);
}
}
}
if("-sdown".equals(channel)){//节点上线
String[]messages=message.split("");
if(messages.length==8){
if("slave".equals(messages[0])){
if(masterNames.contains(messages[5])){
StringslaveIp=messages[2];
StringslavePort=messages[3];
StringmasterIp=messages[6];
StringmasterPort=messages[7];
logger.info("Foundavailableredisslave[{}]formaster[{}@{}]",slaveIp+":"+slavePort,messages[5],masterIp+":"+masterPort);
initSentinelPool();
}else{
logger.error("Ignoringmessageon-sdownformastername{},butourmasternameis{}!",messages[5],masterNames);
}
}else{
logger.error("InvalidmessagereceivedonSentinel{}onchannel-sdown:{}",host+":"+port,message);
}
}
}
if("+switch-master".equals(channel)){//主从节点切换
String[]messages=message.split("");
if(messages.length==5){
if(masterNames.contains(messages[0])){
StringoldMasterIp=messages[1];
StringoldMasterPort=messages[2];
StringnewMasterIp=messages[3];
StringnewMasterPort=messages[4];
logger.info("Switchmaster{}from[{}]to[{}]",messages[0],oldMasterIp+":"+oldMasterPort,newMasterIp+":"+newMasterPort);
initSentinelPool();
}else{
logger.error("Ignoringmessageon+switch-masterformastername{},butourmasternameis{}!",messages[5],masterNames);
}
}else{
logger.error("...

【专利技术属性】
技术研发人员:刘青松王锋王文波刘本中司震魏阳
申请(专利权)人:南京联创信息科技有限公司
类型:发明
国别省市:江苏;32

网友询问留言 已有0条评论
  • 还没有人留言评论。发表了对其他浏览者有用的留言会获得科技券。

1