redis-cluster与spring-data-redis集成

因为redis3.0才出来,spring-data-redis正式版本还没有支持redis-cluster。大概上官网看了一下,发现只有1.7.0.RC1才支持,同时没有找到关于jedis与spring-data-redis集成RedisTemplate的资料,所以看了一下原码,写了下面关于RedisTemplate的配置。
引用

一、redis-cluster构造
引用


二、与spring-data-redis集成
1.JedisCluster
以集群方式使用连接池,来直接使用redis相关命令。
spring.xml
	<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
		<property name="maxTotal" value="${redis.maxTotal}" />
		<property name="maxIdle" value="${redis.maxIdle}" />
		<property name="maxWaitMillis" value="${redis.maxWaitMillis}" />
		<property name="testOnBorrow" value="${redis.testOnBorrow}" />
		<property name="testOnReturn" value="${redis.testOnReturn}" />
	</bean>

    <bean id="redisConnectionFactory"
        class="com.sinowel.eacpa.test.JedisClusterFactory">
        <property name="addressConfig">
            <value>classpath:connect-redis.properties</value>
        </property>
        <!-- 属性文件里 key的前缀 -->
        <property name="addressKeyPrefix" value="address" />

        <property name="timeout" value="300000" />
        <property name="maxRedirections" value="6" />
        <property name="genericObjectPoolConfig" ref="jedisPoolConfig" />
    </bean>

connect-redis.properties
address1=192.168.71.188:6380
address2=192.168.71.188:6381
address3=192.168.71.188:6382
address4=192.168.71.188:7380
address5=192.168.71.188:7381
address6=192.168.71.188:7382

import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Pattern;

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;

import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;

public class JedisClusterFactory implements FactoryBean<JedisCluster>, InitializingBean {

    private Resource addressConfig;
    private String addressKeyPrefix ;

    private JedisCluster jedisCluster;
    private Integer timeout;
    private Integer maxRedirections;
    private GenericObjectPoolConfig genericObjectPoolConfig;
    
    private Pattern p = Pattern.compile("^.+[:]\\d{1,5}\\s*$");

    @Override
    public JedisCluster getObject() throws Exception {
        return jedisCluster;
    }

    @Override
    public Class<? extends JedisCluster> getObjectType() {
        return (this.jedisCluster != null ? this.jedisCluster.getClass() : JedisCluster.class);
    }

    @Override
    public boolean isSingleton() {
        return true;
    }



    private Set<HostAndPort> parseHostAndPort() throws Exception {
        try {
            Properties prop = new Properties();
            prop.load(this.addressConfig.getInputStream());

            Set<HostAndPort> haps = new HashSet<HostAndPort>();
            for (Object key : prop.keySet()) {

                if (!((String) key).startsWith(addressKeyPrefix)) {
                    continue;
                }

                String val = (String) prop.get(key);

                boolean isIpPort = p.matcher(val).matches();

                if (!isIpPort) {
                    throw new IllegalArgumentException("ip 或 port 不合法");
                }
                String[] ipAndPort = val.split(":");

                HostAndPort hap = new HostAndPort(ipAndPort[0], Integer.parseInt(ipAndPort[1]));
                haps.add(hap);
            }

            return haps;
        } catch (IllegalArgumentException ex) {
            throw ex;
        } catch (Exception ex) {
            throw new Exception("解析 jedis 配置文件失败", ex);
        }
    }
    
    @Override
    public void afterPropertiesSet() throws Exception {
        Set<HostAndPort> haps = this.parseHostAndPort();
        
        jedisCluster = new JedisCluster(haps, timeout, maxRedirections,genericObjectPoolConfig);
//        jedisCluster = new JedisCluster(haps, timeout, genericObjectPoolConfig);
    }
    public void setAddressConfig(Resource addressConfig) {
        this.addressConfig = addressConfig;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    public void setMaxRedirections(int maxRedirections) {
        this.maxRedirections = maxRedirections;
    }

    public void setAddressKeyPrefix(String addressKeyPrefix) {
        this.addressKeyPrefix = addressKeyPrefix;
    }

    public void setGenericObjectPoolConfig(GenericObjectPoolConfig genericObjectPoolConfig) {
        this.genericObjectPoolConfig = genericObjectPoolConfig;
    }

}

引用


2.RedisTemplate
以集群方式使用连接池,来使用模板进行数据操作,key与value自动序列化存储。
spring.xml
	<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
		<property name="maxTotal" value="${redis.maxTotal}" />
		<property name="maxIdle" value="${redis.maxIdle}" />
		<property name="maxWaitMillis" value="${redis.maxWaitMillis}" />
		<property name="testOnBorrow" value="${redis.testOnBorrow}" />
		<property name="testOnReturn" value="${redis.testOnReturn}" />
	</bean>

    <!-- <bean id="redisNode" class="org.springframework.data.redis.connection.RedisNode">
        <property name=""></property>
    </bean> -->
    <bean id="redisClusterConfig" class="org.springframework.data.redis.connection.RedisClusterConfiguration">
        <property name="maxRedirects" value="3" />
        <property name="clusterNodes">
            <set>
                <!-- <ref bean="redisNode" /> -->
                
	            <bean class="org.springframework.data.redis.connection.RedisNode">
	                <constructor-arg name="host" value="192.168.71.188"></constructor-arg> 
	                <constructor-arg name="port" value="7380"></constructor-arg>
	            </bean>
                <!-- <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="192.168.71.188"></constructor-arg> 
                    <constructor-arg name="port" value="6381"></constructor-arg>
                </bean>
                <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="192.168.71.188"></constructor-arg> 
                    <constructor-arg name="port" value="6382"></constructor-arg>
                </bean> -->
            </set>
        </property>
    </bean>
    
    <bean id="redis4CacheConnectionFactory"
		class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <constructor-arg name="clusterConfig" ref="redisClusterConfig" />
        
		<property name="hostName" value="${redis.host}"/>
		<property name="port" value="${redis.port}"/>
		<property name="timeout" value="${redis.timeout}" />
		<property name="poolConfig" ref="jedisPoolConfig"/>
	</bean>

	<bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer" />
	<bean id="redis4CacheTemplate" class="org.springframework.data.redis.core.RedisTemplate">
		<property name="connectionFactory" ref="redis4CacheConnectionFactory" />
        <!-- <property name="keySerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
        </property> -->
        <property name="keySerializer" ref="stringRedisSerializer" />
        <property name="hashKeySerializer" ref="stringRedisSerializer" />
        <property name="valueSerializer" ref="stringRedisSerializer" />
        <property name="hashValueSerializer" ref="stringRedisSerializer" />
	</bean>


引用
spring-data-redis提供了多种serializer策略,这对使用jedis的开发者而言,实在是非常便捷。sdr提供了4种内置的serializer:
JdkSerializationRedisSerializer:使用JDK的序列化手段(serializable接口,ObjectInputStrean,ObjectOutputStream),数据以字节流存储
StringRedisSerializer:字符串编码,数据以string存储
JacksonJsonRedisSerializer:json格式存储
OxmSerializer:xml格式存储
其中JdkSerializationRedisSerializer和StringRedisSerializer是最基础的序列化策略,其中“JacksonJsonRedisSerializer”与“OxmSerializer”都是基于stirng存储,因此它们是较为“高级”的序列化(最终还是使用string解析以及构建java对象)。
RedisTemplate中需要声明4种serializer,默认为“JdkSerializationRedisSerializer”:
    1) keySerializer :对于普通K-V操作时,key采取的序列化策略
    2) valueSerializer:value采取的序列化策略
    3) hashKeySerializer: 在hash数据结构中,hash-key的序列化策略
    4) hashValueSerializer:hash-value的序列化策略
    无论如何,建议key/hashKey采用StringRedisSerializer。
http://www.360doc.com/content/15/0513/21/1073512_470277654.shtml

3. 测试代码
@Service
public class TestService {

    @Resource
    private JedisCluster redisConnectionFactory;
//
    @Resource
    private RedisTemplate redis4CacheTemplate;
    
    public void test() {
        System.out.println(redisConnectionFactory.get("t1"));
        System.out.println(redisConnectionFactory.get("aa"));
        System.out.println(redisConnectionFactory.get("cc"));
        System.out.println("----------------");
        redis4CacheTemplate.opsForValue().set("aa", "300人");
        redis4CacheTemplate.opsForValue().set("cc", "AA1");
        redis4CacheTemplate.opsForValue().set("t4", "BB");
        System.out.println(redis4CacheTemplate.opsForValue().get("aa"));
        System.out.println(redis4CacheTemplate.opsForValue().get("cc"));
        System.out.println(redis4CacheTemplate.opsForValue().get("t44"));

    }
}

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.BlockJUnit4ClassRunner;

import com.sinowel.eacpa.BaseTest;
import com.sinowel.eacpa.test.service.TestService;

@RunWith(BlockJUnit4ClassRunner.class)
public class TestDemo extends BaseTest{

    public TestDemo() {
        super("classpath:spring/spring.xml");
    }
        
    @Test //测试构造注入
    public void testCons() {
        TestService service = super.getBean("testService");
        service.test();
        System.out.println("success");
    }
}

控制台输出:
100
300人
AA1
----------------
300人
AA1
null

猜你喜欢

转载自langmnm.iteye.com/blog/2286858