Redis-Cluster集群整合SpringCache

前言

    SpringCache不支持集群,只适用于单机环境,集群环境下,每台服务器的spring cache就会不同步,这样就会产生问题,同时SpringCache是代码级的缓存,实际上还是使用的JVM的内存来缓存对象。Redis 作为一个缓存服务器,是内存级的缓存,它是使用单纯的内存来进行缓存,同时redis设置单独的缓存服务器,所有集群服务器统一访问redis,不会出现缓存不同步的情况。Redis和Springcahe进行整合,既能够方便的缓存对象,提升性能,也可以支持集群环境。当然redis不是必须的,其他缓存也是可以的。

Redis集群的搭建

  关于redis的集群搭建我在前边的文章中已经介绍过了,请参考:Redis-Cluster集群搭建。

项目下载

项目参考:Redis-SpringCache

Redis整合Spring

  maven依赖

 
    <dependencies>
        
        <dependency>
            <groupId>joda-timegroupId>
            <artifactId>joda-timeartifactId>
            <version>2.5version>
        dependency>
        
        <dependency>
            <groupId>org.apache.commonsgroupId>
            <artifactId>commons-lang3artifactId>
            <version>3.3.2version>
        dependency>
        <dependency>
            <groupId>org.apache.commonsgroupId>
            <artifactId>commons-ioartifactId>
            <version>1.3.2version>
        dependency>
        <dependency>
            <groupId>commons-netgroupId>
            <artifactId>commons-netartifactId>
            <version>3.3version>
        dependency>
        
        <dependency>
            <groupId>com.fasterxml.jackson.coregroupId>
            <artifactId>jackson-databindartifactId>
            <version>2.4.2version>
        dependency>
        
        <dependency>
            <groupId>org.apache.httpcomponentsgroupId>
            <artifactId>httpclientartifactId>
            <version>4.3.5version>
        dependency>
        
        <dependency>
            <groupId>junitgroupId>
            <artifactId>junitartifactId>
            <version>4.12version>
            <scope>testscope>
        dependency>
        
        <dependency>
            <groupId>org.slf4jgroupId>
            <artifactId>slf4j-log4j12artifactId>
            <version>1.6.4version>
        dependency>
        <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-contextartifactId>
                <version>4.2.6.RELEASEversion>
            dependency>
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-beansartifactId>
                <version>4.2.6.RELEASEversion>
            dependency>
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-webmvcartifactId>
                <version>4.2.6.RELEASEversion>
            dependency>
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-jdbcartifactId>
                <version>4.2.6.RELEASEversion>
            dependency>
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-aspectsartifactId>
                <version>4.2.6.RELEASEversion>
            dependency>
            
            <dependency>
                <groupId>javax.servletgroupId>
                <artifactId>servlet-apiartifactId>
                <version>2.5version>
                <scope>providedscope>
            dependency>
            <dependency>
                <groupId>javax.servletgroupId>
                <artifactId>jsp-apiartifactId>
                <version>2.0version>
                <scope>providedscope>
            dependency>
            
            <dependency>
                <groupId>redis.clientsgroupId> 
                <artifactId>jedisartifactId>
                <version>2.9.0version>
            dependency>
             
            <dependency>  
              <groupId>org.springframework.datagroupId>  
              <artifactId>spring-data-redisartifactId>  
              <version>1.8.1.RELEASEversion>  
            dependency>
            
            <dependency>
                <groupId>org.mybatisgroupId>
                <artifactId>mybatisartifactId>
                <version>3.2.8version>
            dependency>
            <dependency>
                <groupId>org.mybatisgroupId>
                <artifactId>mybatis-springartifactId>
                <version>1.2.2version>
            dependency>
            <dependency>
                <groupId>com.github.miemiedevgroupId>
                <artifactId>mybatis-paginatorartifactId>
                <version>1.2.15version>
            dependency>
            
            <dependency>
                <groupId>mysqlgroupId>
                <artifactId>mysql-connector-javaartifactId>
                <version>5.1.32version>
            dependency>
            
            <dependency>
                <groupId>com.alibabagroupId>
                <artifactId>druidartifactId>
                <version>1.0.9version>
            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配置文件

  
<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">

        
    <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>

      
    <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>
      
    <bean id="redisClusterConfiguration" class="org.springframework.data.redis.connection.RedisClusterConfiguration">  
        <constructor-arg name="propertySource" ref="resourcePropertySource"/>  
    bean>  
      
    <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" />  
          
        <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 >  

        
     <bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">    
         <property name="caches">    
            <set>    
                  
                <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 redisTemplate;
    private String name;

    public RedisTemplate getRedisTemplate() {
        return redisTemplate;
    }

    public void setRedisTemplate(RedisTemplate 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() {
            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() {
            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;
            }
        });
    }
    /**
     * 描述 : . 
*

* <使用方法说明> *

* * @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; } /** * 描述 : .
*

* <使用方法说明> *

* * @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() { 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() { public String doInRedis(RedisConnection connection) throws DataAccessException { connection.flushDb(); return "ok"; } }); } @Override public T get(Object key, Class 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 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/70478281
http://blog.csdn.net/wjacketcn/article/details/50945887

你可能感兴趣的:(redis)