`

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
分享到:
评论
1 楼 songsir01 2018-04-08  
Invalid property 'maxRedirects' of bean class [org.springframework.data.redis.connection.RedisClusterConfiguration]: Bean property 'maxRedirects' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
这是什么原因呢

相关推荐

Global site tag (gtag.js) - Google Analytics