1. 程式人生 > >Spring 整合redis叢集 實現 以及過程中需要注意的問題點

Spring 整合redis叢集 實現 以及過程中需要注意的問題點

一,準備工作:

1.首先安裝好redis叢集,啟動並配置叢集。

2.SpringMVC環境,看專案或個人需要,可以使SpringMVC的web專案,也可以是隻使用SpringBean管理器。

二,著手配置:

由於專案是由maven管理的所以需要的jar 包新增到maven 的pom檔案即可

1.新增jar依賴,再maven pom.xml 檔案中新增依賴如下:// 這裡需要說明下,依賴的jar包 redis.client  和 spring-data-redis 的版本匹配問題 實驗了好幾個對應如下

       redis.client  2.9.0 ---- spring-data-redis  1.7.1.RELEASE

       redis.client 2.9.0 -----spring-data-redis   1.7.2.RELEASE    這兩個是可以使用的

       由於版本不匹配,遇到的錯誤如下:

         1. ClassNotFoundException  : redis/client/util/geoUtils    說這個類找不到。

         2. org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'redisTemplate' defined in class path resource [applicationContext.xml]

             說建立 redisTemplate bean 物件時失敗了。

           <!-- jedis (一個redis client端的jar)-->

          <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency>

         <!-- spring-data-redis 依賴-->

        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-redis</artifactId>
            <version>1.7.1.RELEASE</version>
        </dependency>

2.配置redis 配置檔案 我把它單獨提取出來放在一個配置檔案(spring-data-redis-cluster.xml)中,然後import 到 spring ApplicationContext.xml 檔案中:

spring-data-redis-cluster.xml 配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:task="http://www.springframework.org/schema/task" 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.1.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
    http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
    http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">

     <!--  redis連線池  這裡引用的是jedis 包中的功能  -->
    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxTotal" value="${redis.maxActive:1024}" />
        <property name="maxIdle" value="${redis.maxIdle:1024}" />
        <property name="maxWaitMillis" value="${redis.maxWait:10000}" />
        <property name="testOnBorrow" value="${redis.testOnBorrow:true}" />
        <property name="testOnReturn" value="${redis.testOnReturn:true}" />
    </bean>

    <!-- Redis叢集配置     這裡使用的是spring-data-redis  包中內容 -->
     <bean id="redisClusterConfig" class="org.springframework.data.redis.connection.RedisClusterConfiguration">
        <property name="maxRedirects" value="6"></property>
        <property name="clusterNodes">
            <set>
                <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="192.168.1.105"></constructor-arg>
                    <constructor-arg name="port" value="7111"></constructor-arg>
                </bean>

                <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="192.168.1.105"></constructor-arg>
                    <constructor-arg name="port" value="7112"></constructor-arg>
                </bean>
                <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="192.168.1.105"></constructor-arg>
                    <constructor-arg name="port" value="7116"></constructor-arg>
                </bean>
                <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="192.168.1.102"></constructor-arg>
                    <constructor-arg name="port" value="7113"></constructor-arg>
                </bean>
                 <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="192.168.1.102"></constructor-arg>
                    <constructor-arg name="port" value="7114"></constructor-arg>
                </bean>
                 <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="192.168.1.102"></constructor-arg>
                    <constructor-arg name="port" value="7115"></constructor-arg>
                </bean>
            </set>
        </property>
    </bean>
    <!-- Redis連線工廠     -->
    <bean id="redis4CacheConnectionFactory"
        class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <constructor-arg name="clusterConfig" ref="redisClusterConfig" />
        <property name="timeout" value="${redis.timeout:10000}" />
        <property name="poolConfig" ref="jedisPoolConfig" />
    </bean>
    <!-- 儲存序列化 -->
    <bean name="stringRedisSerializer"
        class="org.springframework.data.redis.serializer.StringRedisSerializer" />

    <!-- 叢集Resis使用模板 -->
    <bean id="clusterRedisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="redis4CacheConnectionFactory" />
        <property name="keySerializer" ref="stringRedisSerializer" />
        <property name="hashKeySerializer" ref="stringRedisSerializer" />
        <property name="valueSerializer" ref="stringRedisSerializer" />
        <property name="hashValueSerializer" ref="stringRedisSerializer" />
    </bean>

</beans>

3.再ApplicationContent.xml 配置檔案中 匯入以上配置:

<!-- 匯入rediscluster配置檔案 -->
    <import resource="classpath:spring-data-redis-cluster.xml" />

4.redisTemplate  的應用:

自定義一個redisClient類來管理操作 redis 的存取操作:我定義的是:RedisClusterClient.java 類,內容如下:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
@Service
public class RedisClusterClient {

        // 由於在Spring ApplicationContext.xml 配置檔案中匯入了 redis的配置檔案,也就間接的將 <bean id="clusterRedisTemplate"                                                                  class="org.springframework.data.redis.core.RedisTemplate">  這個Bean託管給了Spring bean容器來管理所以 只要我使用註解就可以把這個模板類物件引用過來。

       @Autowired
       private RedisTemplate<String,String> clusterRedisTemplate;
    
       //新增資料
        public void put(Object key, Object value) {
            if(null == value) {
                return;
            }
    
            if(value instanceof String) {
                if(StringUtils.isEmpty(value.toString())) {
                    return;
                }
            }
    
            // TODO Auto-generated method stub
            final String keyf = key + "";
            final Object valuef = value;
            final long liveTime = 86400;
    
            clusterRedisTemplate.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;
                }
            });
        }
    

         // 獲取資料

        public Object get(Object key) {
            final String keyf = (String) key;
            Object object;
            object = clusterRedisTemplate.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;
        }
    
        /**
         * 描述 : <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;
        }
    
        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;
        }
    
}

5.以上配置+實現。