说明:适合测试且了解sentinel模式,线上项目慎用。
一、配置情况说明:
Master: 端口 6381
Slave 端口 6379、6380
Sentinel 端口 26379
二、集成spring-data-redis
2.1配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.tablemiao.redis.dao"></context:component-scan>
<context:property-placeholder location="classpath:applicationContext.properties" />
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="maxTotal" value="${redis.maxActive}" />
<property name="maxWaitMillis" value="${redis.maxWait}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>
<bean id="redisSentinelConfiguration"
class="org.springframework.data.redis.connection.RedisSentinelConfiguration">
<property name="master">
<bean class="org.springframework.data.redis.connection.RedisNode">
<property name="name" value="mymaster" />
</bean>
</property>
<property name="sentinels">
<set>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="192.168.1.118"></constructor-arg>
<constructor-arg name="port" value="26379"></constructor-arg>
</bean>
</set>
</property>
</bean>
<bean id="jedisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="poolConfig" ref="poolConfig"/>
<constructor-arg ref="redisSentinelConfiguration"></constructor-arg>
<property name="usePool" value="false"/>
<property name="hostName" value="${redis.hostName}" />
<property name="port" value="${redis.port}" />
</bean>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory" />
</bean>
</beans>
网上看了很多配法,解释的都不完整,有些根本不能运行,共同学习。
poolConfig 连接池配置 可以忽略,因为<property name="usePool" value="false"/>
配了这句,如果启用,读取配置就会出错,始终没有解决,可以直接删除掉。
redisSentinelConfiguration 哨兵的配置,host、port为sentinel的监听端口和host(有人说是redis服务进程的端口和host,不知道怎么玩的,说的不清不楚,一直出错,查看过这个类,也不该这么配),本人是一个sentinel.conf文件中监听三个redis进程(就是Redis(六)中的配法),所以只有一个,多个可以在set中添加。
jedisConnectionFactory 配置连接工厂、默认端口为master的端口,以方便后续测试。
2.2加载上诉配置文件 直接拿到注入的redisTemplate 进行数据操作,读写无异常。
2.3断开master进程、主从切换,后台切换完成,重新加入开始master,此时master变为slave详见Redis(六)
2.4 再次通过redisTemplate 进行样例操作,发现,此时读取可以,但是写数据不行。原因为,代码中的连接地址依旧为开始master连接的地址和端口。
2.5 问人找文档无果。仔细查看redis的连接模式,想到如下法子,测试可行,性能没测试过。
2.5.1通过redisTemplate.getConnectionFactory().getSentinelConnection().masters();可以获取当前的master连接地址和端口。
2.5.2获取配置文件中当前连接地址和端口比对,如果一致,说明当前连接为master,可以进行读写,直接利用注入的redisTemplate进行操作即可,如果不一致,利用当前master的地址和端口在代码里重新建立连接,进行写操作。
2.6比对的逻辑代码(整体代码详见cc-redis-three)
//获取当前的master
public String getMaster() {
Iterator<RedisServer> masters = redisTemplate.getConnectionFactory()
.getSentinelConnection().masters().iterator();
while(masters.hasNext()){
return masters.next().asString();
}
return "get_master_error";
}
//连接的逻辑比对。 如果一致,就返回redisTemplate,否则返回jedis连接
public Object getMasterRedisTemplate(){
String proptiesHostAndPort = hostName+":"+port;
String mHost = getMaster().split(":")[0];
int mPort = Integer.parseInt(getMaster().split(":")[1]);
//如果当前连接为master,直接返回,用作写操作
if(proptiesHostAndPort.equals(getMaster())){
return redisTemplate;
}else{
//获取master 的连接方式 再次建立连接,进行写操作
/*
本想通过这种方式,返回一个RedisTemplate 结果发现获取不到连接,希望大神弄好了,一起学习
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory();
jedisConnectionFactory.setHostName(hostName);
jedisConnectionFactory.setPort(port);
RedisTemplate<String, Object> re= new RedisTemplate<String, Object>();
re.setConnectionFactory(jedisConnectionFactory);
//这种也不行
JedisConnection jedis = jedisConnectionFactory.getConnection();
*/
//直接jedis 操作
JedisPoolConfig jpl = new JedisPoolConfig();
jpl.setMaxTotal(50000);
jpl.setMaxIdle(5);
jpl.setMaxWaitMillis(1000*60*5);
jpl.setTestOnBorrow(true);
JedisPool jp = new JedisPool(jpl,mHost,mPort);
return jp.getResource();
}
}
2.7 获取到2.6中的连接,分别利用其进行操作,读,写代码
写,如果返回是的RedisTemplate,说明是当前是master的连接,直接写数据即可,否则
创建一个master的jedis连接 进行写数据
public boolean insertString(String key, String value) {
try {
//先拿连接判断,是否当前连接为master,底下insert相同处理即可
if(getMasterRedisTemplate() instanceof RedisTemplate){
redisTemplate.opsForValue().set(key, value);
}else{
Jedis jedis = (Jedis)getMasterRedisTemplate();
jedis.set(key, value);
}
return true;
} catch (Exception e) {
logger.info("新增错误:{}", e.getMessage());
return false;
}
}
读,一样的判断即可
public Object select(String key){
try {
if(getMasterRedisTemplate() instanceof RedisTemplate){
DataType type = redisTemplate.type(key);
if(DataType.NONE == type){
logger.info("key不存在");
return null;
}else if(DataType.STRING == type){
return super.redisTemplate.opsForValue().get(key);
}else if(DataType.LIST == type){
return super.redisTemplate.opsForList().range(key, 0, -1);
}else if(DataType.HASH == type){
return super.redisTemplate.opsForHash().entries(key);
}else
return null;
}else{
Jedis jedis = (Jedis)getMasterRedisTemplate();
if("string".equals(jedis.type(key))){
return jedis.get(key);
}else{
return null;
}
}
} catch (Exception e) {
logger.info("查询错误:{}", e.getMessage());
return null;
}
}
若是想要达到master 写 slave读,在读的时候判断即可,如果是当前的master连接,那创建一个slave的jedis进行读取。
三、测试
@org.junit.Test
public void test() throws Exception{
logger.info("=========start===========");
logger.info("当前master列表:{}",customDao.getMaster());
//logger.info("当前连接的hostName:{}",customDao.isMaster());
customDao.insertString("sentinel:key:1", "sentinel_value_集群值测试1");
logger.info("读取集群配置的值:{}",customDao.select("sentinel:key:1"));
logger.info("=========end===========");
}
结果如下,当前连接是的slave,也能读写
相关推荐
redis-sentinel 就像他的名字一样,他是一个哨兵,监控 master 状态,如果超过规定时间没有响应,则自动进行主从切换,期间会有一段时间(决定于具体的配置参数)redis集群无法提供服务 。原理类似 mysql 的 MHA。...
Spring集成redis集群
Redis 是一个开源的 key-value 存储系统,由于出众的性能,大部分互联网企业都用来做服务器端缓存。Redis 支持单实例模式,集群主从模式、哨兵模式等部署
在使用代码之前,需要你配置reids集群,在百度上你可以找到
Spring + redis集群的集成 spring-data-redis-1.8.1.RELEASE.jar jedis-2.9.0.jar spring-data-commons-1.8.1.RELEASE.jar commons-pool2-2.4.2.jar
Springboot整合Redis集群,零配置方式;另外用AOP实现了操作缓存的三套自定义注解,有兴趣的小伙伴可以试试看.
spring + redis + sentinel 配置文件,同学们可以下载使用,有问题请指教。
redis-sentinel(哨兵机制)集群安装包,解压即可使用;在linux环境上快速搭建一个简单的基于哨兵模式的redis集群
redis-sentinel 基于 phpredis 扩展的 redis-sentinel 客户端
redis-sentinel集群及双机热备
采用spring-data-redis 搭建redis集群,代码包含redis工具类,可存储对象集合,maven项目,部署可运行。
SpringCloud整合Redis缓存;版本:SpringCloud :Dalston.SR4;SpringBoot:1.5.14.RELEASE;Redis:3.2.0;Maven :3.5.3.代码下载下来即可用
因为Redis实例在各个大公司的应用,每个公司都需要一个Redis集群的管理工具,被迫都自己写管理工具来管理Redis集群,antirez考虑到社区的急迫需要(详情),花了几个星期写出了Redis-sentinel。 Redis-sentinel的三大...
spring boot+redis单机与集群.zip spring boot+redis单机与集群.zip spring boot+redis单机与集群.zip
本源代码提供了redis3.0或者redis3.2如何集群,以及spring-data-redis如何操作集群,并且同时提供了redis单例操作
Redis sentinel集群实验 包含完整的环境搭建,实验步骤,实验截图等
本文档基于以前写的《Redis-3.0.5集群配置》和《Redis-4.0.11集群配置》。 redis-3.0.0开始支持集群,redis-4.0.0开始支持module,redis-5.0.0开始支持类似于kafka那样的消息队列。 本文参考官方文档而成:...
Windos系统的Redis sentinel集群。 启动命令:D:\redis-2.8.18.rar\redis-2.8.18>redis-server.exe sentinel.conf --sentinel
Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装...
redis3.0 widows集群 spring整合jedis redis搭建window集群代码和文档rubygems-2.5.1和rubyinstaller-2.2.3-x64软件下载