Redis-Cluster集群整合SpringCache
2017-12-18 20:45
405 查看
前言
SpringCache不支持集群,只适用于单机环境,集群环境下,每台服务器的spring cache就会不同步,这样就会产生问题,同时SpringCache是代码级的缓存,实际上还是使用的JVM的内存来缓存对象。Redis 作为一个缓存服务器,是内存级的缓存,它是使用单纯的内存来进行缓存,同时redis设置单独的缓存服务器,所有集群服务器统一访问redis,不会出现缓存不同步的情况。Redis和Springcahe进行整合,既能够方便的缓存对象,提升性能,也可以支持集群环境。当然redis不是必须的,其他缓存也是可以的。Redis集群的搭建
关于redis的集群搭建我在前边的文章中已经介绍过了,请参考:Redis-Cluster集群搭建。项目下载
项目参考:Redis-SpringCacheRedis整合Spring
maven依赖
<!-- 依赖管理 --> <dependencies> <!-- 时间操作组件 --> <dependency> <groupId>joda-time</groupId> <artifactId>joda-time</artifactId> <version>2.5</version> </dependency> <!-- Apache工具组件 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> &l 4000 t;version>3.3.2</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-io</artifactId> <version>1.3.2</version> </dependency> <dependency> <groupId>commons-net</groupId> <artifactId>commons-net</artifactId> <version>3.3</version> </dependency> <!-- Jackson Json处理工具包 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.4.2</version> </dependency> <!-- httpclient --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.3.5</version> </dependency> <!-- 单元测试 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- 日志处理 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.6.4</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.2.6.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>4.2.6.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.2.6.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.2.6.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>4.2.6.RELEASE</version> </dependency> <!-- 编译程序用的 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jsp-api</artifactId> <version>2.0</version> <scope>provided</scope> </dependency> <!-- Redis客户端 --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency> <!-- redis Spring 基于注解配置 --> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.8.1.RELEASE</version> </dependency> <!-- Mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.2.8</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>com.github.miemiedev</groupId> <artifactId>mybatis-paginator</artifactId> <version>1.2.15</version> </dependency> <!-- MySql --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.32</version> </dependency> <!-- 连接池 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.9</version> </dependency>
redis.properties配置文件
#密码 redis.password=123456 #最大空闲数 redis.maxIdle=100 #最大连接数 redis.maxActive=300 #最大建立连接等待时间 redis.maxWait=1000 #客户端超时时间单位是毫秒 redis.timeout=100000 redis.maxTotal=1000 redis.minIdle=8 #是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个 redis.testOnBorrow=true spring.redis.cluster.nodes=192.168.251.129\:7001,192.168.251.129\:7002,192.168.251.129\:7003,192.168.251.129\:7004,192.168.251.129\:7005,192.168.251.129\:7006 spring.redis.cluster.max-redirects=3
applicationContext-redis.xml配置文件
<?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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:cache="http://www.springframework.org/schema/cache" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.2.xsd"> <!-- 启用缓存注解功能,这个是必须的,否则注解不会生效,另外,该注解一定要声明在spring主配置文件中才会生效 --> <cache:annotation-driven cache-manager="cacheManager" /> <!-- 引入配置文件 --> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="classpath:properties/redis.properties" /> </bean> <!-- jedis 配置--> <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig" > <!--最大空闲数--> <property name="maxIdle" value="${redis.maxIdle}" /> <!--最大建立连接等待时间--> <property name="maxWaitMillis" value="${redis.maxWait}" /> <!--是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个--> <property name="testOnBorrow" value="${redis.testOnBorrow}" /> </bean > <!--配置文件加载--> <bean id="resourcePropertySource" class="org.springframework.core.io.support.ResourcePropertySource"> <constructor-arg name="name" value="redis.properties"/> <constructor-arg name="resource" value="classpath:properties/redis.properties"/> </bean> <!--redisCluster配置--> <bean id="redisClusterConfiguration" class="org.springframework.data.redis.connection.RedisClusterConfiguration"> <constructor-arg name="propertySource" ref="resourcePropertySource"/> </bean> <!-- redis服务器中心 --> <bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" > <constructor-arg name="clusterConfig" ref="redisClusterConfiguration"/> <constructor-arg name="poolConfig" ref="poolConfig"/> <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" /> <!--如果不配置Serializer,那么存储的时候缺省使用String,如果用User类型存储,那么会提示错误User can't cast to String!! --> <property name="keySerializer" > <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" /> </property> <property name="valueSerializer" > <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" /> </property> <property name="hashKeySerializer"> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/> </property> <property name="hashValueSerializer"> <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/> </property> </bean > <!-- spring自己的缓存管理器,这里定义了缓存位置名称 ,即注解中的value --> <bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager"> <property name="caches"> <set> <!-- 这里可以配置多个redis --> <bean class="org.lpl.RedisDemo.redis.RedisCache"> <property name="redisTemplate" ref="redisTemplate" /> <property name="name" value="defaultCache"/> </bean> </set> </property> </bean> </beans>
RedisCache.class(继承Spring的Cache进行实现重写)
public class RedisCache implements Cache { private RedisTemplate<String, Object> redisTemplate; private String name; public RedisTemplate<String, Object> getRedisTemplate() { return redisTemplate; } public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) { this.redisTemplate = redisTemplate; } public void setName(String name) { this.name = name; } @Override public String getName() { // TODO Auto-generated method stub return this.name; } @Override public Object getNativeCache() { // TODO Auto-generated method stub return this.redisTemplate; } @Override public ValueWrapper get(Object key) { // TODO Auto-generated method stub final String keyf = (String) key; Object object = null; object = redisTemplate.execute(new RedisCallback<Object>() { public Object doInRedis(RedisConnection connection) throws DataAccessException { byte[] key = keyf.getBytes(); byte[] value = connection.get(key); if (value == null) { return null; } return toObject(value); } }); return (object != null ? new SimpleValueWrapper(object) : null); } @Override public void put(Object key, Object value) { // TODO Auto-generated method stub final String keyf = (String) key; final Object valuef = value; final long liveTime = 86400; redisTemplate.execute(new RedisCallback<Long>() { public Long doInRedis(RedisConnection connection) throws DataAccessException { byte[] keyb = keyf.getBytes(); byte[] valueb = toByteArray(valuef); connection.set(keyb, valueb); if (liveTime > 0) { connection.expire(keyb, liveTime); } return 1L; } }); } /** * 描述 : <Object转byte[]>. <br> * <p> * <使用方法说明> * </p> * * @param obj * @return */ private byte[] toByteArray(Object obj) { byte[] bytes = null; ByteArrayOutputStream bos = new ByteArrayOutputStream(); try { ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(obj); oos.flush(); bytes = bos.toByteArray(); oos.close(); bos.close(); } catch (IOException ex) { ex.printStackTrace(); } return bytes; } /** * 描述 : <byte[]转Object>. <br> * <p> * <使用方法说明> * </p> * * @param bytes * @return */ private Object toObject(byte[] bytes) { Object obj = null; try { ByteArrayInputStream bis = new ByteArrayInputStream(bytes); ObjectInputStream ois = new ObjectInputStream(bis); obj = ois.readObject(); ois.close(); bis.close(); } catch (IOException ex) { ex.printStackTrace(); } catch (ClassNotFoundException ex) { ex.printStackTrace(); } return obj; } @Override public void evict(Object key) { // TODO Auto-generated method stub final String keyf = (String) key; redisTemplate.execute(new RedisCallback<Long>() { public Long doInRedis(RedisConnection connection) throws DataAccessException { return connection.del(keyf.getBytes()); } }); } @Override public void clear() { // TODO Auto-generated method stub redisTemplate.execute(new RedisCallback<String>() { public String doInRedis(RedisConnection connection) throws DataAccessException { connection.flushDb(); return "ok"; } }); } @Override public <T> T get(Object key, Class<T> type) { // TODO Auto-generated method stub return null; } @Override public ValueWrapper putIfAbsent(Object key, Object value) { // TODO Auto-generated method stub return null; } }
Service业务代码测试
@Service public class StudentServiceImpl implements StudentService { @Autowired private StudentMapper studentMapper; @Override public int insert(Student student) { // TODO Auto-generated method stub return 0; } @Override @CacheEvict(value="defaultCache",key="'student_id_'+#id") public int deleteByPrimaryKey(Long id) { System.out.println("删除方法执行了"); return studentMapper.deleteByPrimaryKey(id); } @Override @CachePut(value="defaultCache",key="'student_id_'+#student.id") // public Student updateByPrimaryKey(Student student) { System.out.println("修改方法执行了"); studentMapper.updateByPrimaryKey(student); return student; } @Override @Cacheable(value="defaultCache",key="'student_id_'+#id")//#id public Student selectByPrimaryKey(Long id) { System.out.println("查询方法执行了"); return studentMapper.selectByPrimaryKey(id); } @Override public List<Student> selectList() { // TODO Auto-generated method stub return studentMapper.selectList(); } }
SpringCache注解的简单介绍
@Cacheable
@Cacheable可以标记在一个方法上,也可以标记在一个类上。当标记在一个方法上时表示该方法是支持缓存的,当标记在一个类上时则表示该类所有的方法都是支持缓存的。对于一个支持缓存的方法,Spring会在其被调用后将其返回值缓存起来,以保证下次利用同样的参数来执行该方法时可以直接从缓存中获取结果,而不需要再次执行该方法。@CachePut
与@Cacheable相同的是@CachePut也可以声明一个方法支持缓存功能。与@Cacheable不同的是使用@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。@CacheEvict
@CacheEvict是用来标注在需要清除缓存元素的方法或类上的。当标记在一个类上时表示其中所有的方法的执行都会触发缓存的清除操作。标记在方法上就是执行方法是执行出发缓存清除操作。参考资料
http://blog.csdn.net/qq_34021712/article/details/70478281http://blog.csdn.net/wjacketcn/article/details/50945887
相关文章推荐
- SpringMVC整合Redis Cluster集群(带密码)
- 二:redis3.x-cluster集群于spring整合
- springboot2.0整合redis-cluster集群
- Spring整合Redis-Cluster集群实现04
- redis(二)集群 redis-cluster
- redis 3.0 cluster 集群 学习之路篇 [1]
- redis集群 Waiting for the cluster to join 一直等待
- Linux Redis-Cluster集群搭建与使用
- redis cluster 设置密码做集群时gem下client.rb文件修改
- Springboot整合redis及redis集群
- JedisCluster连接redis-cluster集群报错
- 分布式缓存集群方案特性使用场景(Memcache/Redis(Twemproxy/Codis/Redis-cluster))优缺点对比及选型
- redis安装及cluster集群环境搭建
- redis(9)、redis集群之redis Cluster使用
- 基于Cluster的Redis集群方案
- 分布式缓存集群方案特性使用场景(Memcache/Redis(Twemproxy/Codis/Redis-cluster))优缺点对比及选型
- 基于ubuntu搭建Redis(4.0) Cluster 高可用(HA)集群环境
- CentOS 6.5 -- Redis 4.0.2架构☞集群(cluster)的搭建
- Redis集群配置和部署 spring整合redisCluster
- redis cluster集群理解