首先服务器搭建哨兵模式(我这里使用的是Windows8系统),感谢两位博主,少走不少弯路,在此给出链接:服务器哨兵模式搭建和整合哨兵模式

什么一些介绍就不介绍了,可以看一下连接,比较详细,初次接触,当时很迷茫,特纠结整合时候服务器是否需要开启哨兵模式,因为在整合的时候确认了master,结果很显然是需要的

先配置服务器(本地)哨兵模式,直接从redis官网下载安装或者解压版,安装后的目录结构

然后配置哨兵模式

测试采用3个哨兵,1个主redis,2个从redis。
复制6份redis.windows.conf文件并重命名如下(开发者可根据自己的开发习惯进行重命名)
配置master.6378.conf
port:6379
#设置连接密码
requirepass:grs
#连接密码
masterauth:grs

slave.6380.conf配置

port:6380
dbfilename dump6380.rdb
#配置master
slaveof 127.0.0.1 6379

slave.6381.conf配置

port 6381
slaveof 127.0.0.1 6379
dbfilename "dump.rdb"

配置哨兵sentinel.63791.conf(其他两个哨兵配置文件一致,只修改端口号码即可)

port 63791
#主master,2个sentinel选举成功后才有效,这里的master-1是名称,在整合的时候需要一致,这里可以随便更改
sentinel monitor master-1 127.0.0.1 6379 2
#判断主master的挂机时间(毫秒),超时未返回正确信息后标记为sdown状态
sentinel down-after-milliseconds master-1 5000
#若sentinel在该配置值内未能完成failover操作(即故障时master/slave自动切换),则认为本次failover失败。
sentinel failover-timeout master-1 18000
#选项指定了在执行故障转移时, 最多可以有多少个从服务器同时对新的主服务器进行同步,这个数字越小,完成故障转移所需的时间就越长
sentinel config-epoch master-1 2

需要注意的地方

1、若通过redis-cli -h 127.0.0.1 -p 6379连接,无需改变配置文件,配置文件默认配置为bind 127.0.0.1(只允许127.0.0.1连接访问)若通过redis-cli -h 192.168.180.78 -p 6379连接,需改变配置文件,配置信息为bind 127.0.0.1 192.168.180.78(只允许127.0.0.1和192.168.180.78访问)或者将bind 127.0.0.1注释掉(允许所有远程访问)

2、masterauth为所要连接的master服务器的requirepass,如果一个redis集群中有一个master服务器,两个slave服务器,当master服务器挂掉时,sentinel哨兵会随机选择一个slave服务器充当master服务器,鉴于这种机制,解决办法是将所有的主从服务器的requirepass和masterauth都设置为一样。

3、sentinel monitor master-1 127.0.0.1 6379 2 行尾最后的一个2代表什么意思呢?我们知道,网络是不可靠的,有时候一个sentinel会因为网络堵塞而误以为一个master redis已经死掉了,当sentinel集群式,解决这个问题的方法就变得很简单,只需要多个sentinel互相沟通来确认某个master是否真的死了,这个2代表,当集群中有2个sentinel认为master死了时,才能真正认为该master已经不可用了。(sentinel集群中各个sentinel也有互相通信,通过gossip协议)。

依次启动redis

redis-server master.6379.conf

redis-server slave.6380.conf

redis-server slave.6381.conf

redis-server sentinel.63791.conf --sentinel(linux:redis-sentinel sentinel.63791.conf)其他两个哨兵也这样启动

使用客户端查看一下master状态

查看一下哨兵状态

现在就可以在master插入数据,所有的redis服务都可以获取到,slave只能读

整合spring,导入依赖

    <dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.0</version>
</dependency>
<!-- spring-redis -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.6.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.4.2</version>
</dependency>

redis.properties

#redis中心
redis.host=127.0.0.1
#redis.host=10.75.202.11
redis.port=6379
redis.password=
#redis.password=123456
redis.maxTotal=200
redis.maxIdle=100
redis.minIdle=8
redis.maxWaitMillis=100000
redis.maxActive=300
redis.testOnBorrow=true
redis.testOnReturn=true
#Idle时进行连接扫描
redis.testWhileIdle=true
#表示idle object evitor两次扫描之间要sleep的毫秒数
redis.timeBetweenEvictionRunsMillis=30000
#表示idle object evitor每次扫描的最多的对象数
redis.numTestsPerEvictionRun=10
#表示一个对象至少停留在idle状态的最短时间,然后才能被idle object evitor扫描并驱逐;这一项只有在timeBetweenEvictionRunsMillis大于0时才有意义
redis.minEvictableIdleTimeMillis=60000 redis.timeout=100000

配置sentinel方式一

<!-- 这个这个bean是继承RedisSentinelConfiguration,原因是我直接使用时,在注入哨兵的时候spring获取不到注入属性的方法,老是报参数异常 -->
<bean id="redisSentinelConfiguration" class="com.uec.village.redis.RedisConfiguration"><!-- 这里是配置哨兵模式 -->
<constructor-arg name="sentinels">
<set>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.host}"/>
<constructor-arg name="port" value="63791"/>
</bean>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.host}"/>
<constructor-arg name="port" value="63792"/>
</bean>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.host}"/>
<constructor-arg name="port" value="63793"/>
</bean>
</set>
</constructor-arg>
<property name="master">
<bean class="org.springframework.data.redis.connection.RedisNode">
<!--必须指定主节点名称,与服务中的master名称一致-->
<property name="name" value="master-1"/>
<!-- <constructor-arg name="host" value="${redis.host}"/> -->
<!-- <constructor-arg name="port" value="6379"/> -->
</bean>
</property>
</bean>
<!-- 可以直接配置sentinel -->
<!--
<bean id="redisSentinelConfiguration" class="org.springframework.data.redis.connection.RedisSentinelConfiguration">
<property name="sentinels">
<set>
<bean name="sentinelNode1" class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.host}"/>
<constructor-arg name="port" value="63791"/>
</bean>
<bean name="sentinelNode2" class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.host}"/>
<constructor-arg name="port" value="63792"/>
</bean>
<bean name="sentinelNode3" class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.host}"/>
<constructor-arg name="port" value="63793"/>
</bean>
</set>
</property>
<property name="master">
<bean name="masterNode" class="org.springframework.data.redis.connection.RedisNode">
<!--必须指定主节点名称-->
<property name="name" value="mymaster"/>
<!-- <constructor-arg name="host" value="${redis.host}"/>
<constructor-arg name="port" value="6379"/>
-->
</bean>
</property>
</bean>
-->


配置sentinel方式二

<bean id="redisSentinelConfiguration" class="org.springframework.data.redis.connection.RedisSentinelConfiguration">
<constructor-arg name="propertySource" ref="propertySource"/>
</bean> <bean name="propertySource" class="org.springframework.core.io.support.ResourcePropertySource">
<constructor-arg name="location" value="classpath:spring-redis-sentinel.properties" />
</bean>

spring-redis-sentinel.properties内容:

#哨兵监控主redis节点名称,必选
spring.redis.sentinel.master=mymaster
#哨兵节点
spring.redis.sentinel.nodes=192.168.48.31:26379,192.168.48.32:26379,192.168.48.33:26379

xml配置

<!-- jedis 配置 -->  
  <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig" >  
         <property name="maxTotal" value="${redis.maxTotal}" />
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="minIdle" value="${redis.minIdle}" />
<property name="maxWaitMillis" value="${redis.maxWaitMillis}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
<property name="testOnReturn" value="${redis.testOnReturn}" />
<property name="testWhileIdle" value="${redis.testWhileIdle}" />
<property name="timeBetweenEvictionRunsMillis" value="${redis.timeBetweenEvictionRunsMillis}" />
<property name="numTestsPerEvictionRun" value="${redis.numTestsPerEvictionRun}" />
<property name="minEvictableIdleTimeMillis" value="${redis.minEvictableIdleTimeMillis}" />
</bean >
<!-- redis服务器中心 -->
<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" >
<constructor-arg name="sentinelConfig" ref="redisSentinelConfiguration"/>
<constructor-arg name="poolConfig" ref="poolConfig" />
<!-- <property name="poolConfig" ref="poolConfig" /> 如果不是哨兵模式,把这行放开,注释掉上面两行的构造方法注入-->
<property name="port" value="${redis.port}" />
<property name="hostName" value="${redis.host}" />
<property name="password" value="${redis.password}" />
<property name="timeout" value="${redis.timeout}" ></property>
</bean >
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" >
<property name="connectionFactory" ref="connectionFactory" />
<property name="keySerializer" >
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
</property>
<property name="valueSerializer" >
<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
</property>
</bean > <!-- cache配置 -->
<bean id="redisUtil" class="com.uec.village.util.RedisUtil" >
<property name="redisTemplate" ref="redisTemplate" />
</bean >
<bean id="methodCacheInterceptor" class="com.uec.village.interceptor.MethodCacheInterceptor" >
<property name="redisUtil" ref="redisUtil" />
</bean >
  <!-- 配置拦截需要缓存的方法,根绝注解决定 -->
<bean id="methodCachePointCut" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" >
<property name="advice" >
<ref local="methodCacheInterceptor" />
</property>
<property name="patterns" >
<set>
<!-- 确定正则表达式列表 -->
<value>com.service.impl...*ServiceImpl.*</value >
</set>
</property>
</bean >

RedisConfiguration类

import static org.springframework.util.Assert.notNull;

import java.util.Set;

import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.RedisSentinelConfiguration; public class RedisConfiguration extends RedisSentinelConfiguration{ public RedisConfiguration(){}
public RedisConfiguration(Iterable<RedisNode> sentinels){
notNull(sentinels, "Cannot set sentinels to 'null'."); Set<RedisNode> sentinels2 = getSentinels();
if(!sentinels2.isEmpty()){
sentinels2.clear();
} for (RedisNode sentinel : sentinels) {
addSentinel(sentinel);
}
} }

MethodCacheInterceptor拦截器

import java.lang.reflect.Method;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation; import com.uec.village.annotation.RedisCache;
import com.uec.village.util.RedisUtil; /**
* 用户登录过滤器
* @author snw
*
*/
public class MethodCacheInterceptor implements MethodInterceptor {
private RedisUtil redisUtil; /**
* 初始化读取不需要加入缓存的类名和方法名称
*/
public MethodCacheInterceptor() { } @Override
public Object invoke(MethodInvocation invocation) throws Throwable { Object value = null;
String targetName = invocation.getThis().getClass().getName();
Method method = invocation.getMethod();
String methodName = method.getName();
RedisCache annotation = method.getAnnotation(RedisCache.class);
//说明当前方法不需要缓存的,
if(annotation == null){
return invocation.proceed();
}
Object[] arguments = invocation.getArguments();
String key = getCacheKey(targetName, methodName, arguments);
System.out.println(key);
try {
// 判断是否有缓存
if (redisUtil.exists(key)) {
System.out.println("方法名称为:"+methodName+",根据:"+key+",从缓存中获取");
return redisUtil.get(key);
}
// 写入缓存
value = invocation.proceed();
if (value != null) {
final String tkey = key;
final Object tvalue = value;
if(annotation.isTime()){
redisUtil.set(tkey, tvalue); }
}
return value;
} catch (Exception e) {
e.printStackTrace();
if (value == null) {
return invocation.proceed();
}
}
return value;
} /**
* 创建缓存key
*
* @param targetName
* @param methodName
* @param arguments
*/
private String getCacheKey(String targetName, String methodName,
Object[] arguments) {
StringBuffer sbu = new StringBuffer();
sbu.append(targetName).append("_").append(methodName);
if ((arguments != null) && (arguments.length != 0)) {
for (int i = 0; i < arguments.length; i++) {
sbu.append("_").append(arguments[i]);
}
}
return sbu.toString();
} public void setRedisUtil(RedisUtil redisUtil) {
this.redisUtil = redisUtil;
}
}

redis工具类

import java.io.Serializable;
import java.util.Set;
import java.util.concurrent.TimeUnit; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations; /**
* redis工具
* @author snw
*
*/
public class RedisUtil { private RedisTemplate<Serializable, Object> redisTemplate; /**
* 批量删除对应的value
*
* @param keys
*/
public void remove(final String... keys) {
for (String key : keys) {
remove(key);
}
} /**
* 批量删除key
*
* @param pattern
*/
public void removePattern(final String pattern) {
Set<Serializable> keys = redisTemplate.keys(pattern);
if (keys.size() > 0)
redisTemplate.delete(keys);
} /**
* 删除对应的value
*
* @param key
*/
public void remove(final String key) {
if (exists(key)) {
redisTemplate.delete(key);
}
} /**
* 判断缓存中是否有对应的value
*
* @param key
* @return
*/
public boolean exists(final String key) {
return redisTemplate.hasKey(key);
} /**
* 读取缓存
*
* @param key
* @return
*/
public Object get(final String key) {
Object result = null;
ValueOperations<Serializable, Object> operations = redisTemplate
.opsForValue();
result = operations.get(key);
return result;
} /**
* 写入缓存
*
* @param key
* @param value
* @return
*/
public boolean set(final String key, Object value) {
boolean result = false;
try {
ValueOperations<Serializable, Object> operations = redisTemplate
.opsForValue();
operations.set(key, value);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
} /**
* 写入缓存
*
* @param key
* @param value
* @return
*/
public boolean set(final String key, Object value, Long expireTime) {
boolean result = false;
try {
ValueOperations<Serializable, Object> operations = redisTemplate
.opsForValue();
operations.set(key, value);
redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
} public void setRedisTemplate(
RedisTemplate<Serializable, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
}

自定义注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RedisCache {
boolean isCache() default false;
}

到这里可以测试一下,你缓存的数据,是否可以直接使用客户端获取。如有不对的地方欢迎大家扔鸡蛋,以免误人子弟,谢谢!

spring整合redis(哨兵模式)的更多相关文章

  1. Spring Boot(十三):整合Redis哨兵,集群模式实践

    前面的两篇文章(Redis的持久化方案, 一文掌握Redis的三种集群方案)分别介绍了Redis的持久化与集群方案 -- 包括主从复制模式.哨兵模式.Cluster模式,其中主从复制模式由于不能自动做 ...

  2. redis 哨兵模式 Connection refused

    spring整合redis哨兵,修改了bind ,protected 任然连接拒绝,是因为哨兵的mastername 和spring里面的名称不一致..导致拒绝了...... 哨兵模式配置文件 属性  ...

  3. Redis跟Spring整合,sentinel模式

    普通模式整合 一.在pom.xml中引入redis的依赖 <dependency> <groupId>org.springframework.data</groupId& ...

  4. Spring Boot 入门(十):集成Redis哨兵模式,实现Mybatis二级缓存

    本片文章续<Spring Boot 入门(九):集成Quartz定时任务>.本文主要基于redis实现了mybatis二级缓存.较redis缓存,mybaits自带缓存存在缺点(自行谷歌) ...

  5. Spring整合Redis&JSON序列化&Spring/Web项目部署相关

    几种JSON框架用法和效率对比: https://blog.csdn.net/sisyphus_z/article/details/53333925 https://blog.csdn.net/wei ...

  6. Springboot2.x集成Redis哨兵模式

    Springboot2.x集成Redis哨兵模式 说明 Redis哨兵模式是Redis高可用方案的一种实现方式,通过哨兵来自动实现故障转移,从而保证高可用. 准备条件 pom.xml中引入相关jar ...

  7. Redis哨兵模式高可用解决方案

    一.序言 Redis高可用有两种模式:哨兵模式和集群模式,本文基于哨兵模式搭建一主两从三哨兵Redis高可用服务. 1.目标与收获 一主两从三哨兵Redis服务,基本能够满足中小型项目的高可用要求,使 ...

  8. 网站性能优化小结和spring整合redis

    现在越来越多的地方需要非关系型数据库了,最近网站优化,当然从页面到服务器做了相应的优化后,通过在线网站测试工具与之前没优化对比,发现有显著提升. 服务器优化目前主要优化tomcat,在tomcat目录 ...

  9. SpringBoot整合redis哨兵主从服务

    前提环境: 主从配置 http://www.cnblogs.com/zwcry/p/9046207.html 哨兵配置 https://www.cnblogs.com/zwcry/p/9134721. ...

随机推荐

  1. SpringBoot Tomcat启动报错

    中间的桥梁就是下面这个依赖 <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over ...

  2. Bigger-Mai 养成计划,前端基础学习之CSS

    在标签上设置style属性: background-color: #2459a2; height: 48px; ... 编写css样式: 1. 标签的style属性 2. 写在head里面 style ...

  3. MyBatis Generator 自定义生成注释

    注释生成器 为了生成db里面的注释,必须自定义注释生成器 EmptyCommentGenerator: import org.mybatis.generator.api.CommentGenerato ...

  4. windows10下配置环境变量

    环境变量 -> 系统变量中: 新建变量JAVA_HOME,值:jdk的安装路径 新建变量CLASSPATH,值:.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\ ...

  5. LeetCode120-Triangle-数组,动态规划

    题目描述 Problem Description:   Given a triangle, find the minimum path sum from top to bottom. Each ste ...

  6. Hive 导入 parquet 格式数据(未完,待续)

    Hive 导入 parquet 格式数据 Parquet 格式文件,查看Schema Parquet 之mapreduce Hive 导入 parquet 格式数据

  7. LaTex Verbatim 环境下使用数学符号

    参考: Write math and make a box with alltt environment LaTex Verbatim 环境下使用数学符号 在 Verbatim 环境下使用数学符号,需 ...

  8. 后台获取POST方式提交的JSON格式数据

    1.直接使用request.getParamater()的方法获取(这种取参方式对于POST和GET的提交方式均适用): 2.通过请求体的IO流获取参数(这种方式只能用于POST,因为GET方式没有请 ...

  9. 访问github慢的解决方案

    问题描述 打开https://github.com很慢. 解决办法 1.打开文件C:\Windows\System32\drivers\etc\hosts 2.添加如下内容: 151.101.44.2 ...

  10. IDLE清屏扩展

    新建ClearWindows.py,复制以下代码: class ClearWindow: menudefs = [ ('options', [None, ('Clear Shell Window', ...