Skip to content

spring data redis集成jodis的简单实现

lin,wei edited this page Aug 11, 2017 · 4 revisions

#项目要使用spring-data-redis的抽象实现,又要通过jodis实现codisproxy的负载和热备,看到前面issue有提示,就花时间研究了一下。

#如果要使用RedisTemplate的话,它在jedis上抽象了一层JedisConnection,需要把pool放进去,RedisTemplate释放连接使用RedisConnectionUtils.releaseConnection(conn, factory);这个方法最后使用JedisConnection的close(如果有pool就return连接,如果没有就直接quit+disconnect关闭连接),而不是调用Jedis.close(它会判断Datasource即pool是否为空,有则return连接,没有就close掉)。虽然jodis拿到的jedis里带了pool信息,但是取不出来放到JecisConnection,RedisTemplate使用RedisConnectionUtils.releaseConnection 释放连接时,就直接close掉jedis连接而无法return给pool。

#解决方法是:RoundRobinJedisPool.getResource时直接返回JedisConnection.

1. 在RoundRobinJedisPool加返回JedisConnection的方法:

 ` @Override`
`public JedisConnection getResourceForSpringDataRedis() {`
	`ImmutableList<PooledObject> pools = this.pools;`
    `if (pools.isEmpty()) {`
        `throw new JedisException("Proxy list empty");`
    `}`
    `for (;;) {`
        `int current = nextIdx.get();`
        `int next = current >= pools.size() - 1 ? 0 : current + 1;`
        `if (nextIdx.compareAndSet(current, next)) {      `
        	`Pool<Jedis> pool=pools.get(next).pool;`
        	`return new JedisConnection(pool.getResource(),pool,0);`
        `}`
    `}`
	
`}`

2. 实现ConnectionFactory

`public class JodisConnectionFactory implements InitializingBean, DisposableBean, RedisConnectionFactory {`
`private final static Log log = LogFactory.getLog(JodisConnectionFactory.class);`
`private static final ExceptionTranslationStrategy EXCEPTION_TRANSLATION = new PassThroughExceptionTranslationStrategy(`
		`JedisConverters.exceptionConverter());`	
`JedisResourcePool jodisPool;	`
`public JodisConnectionFactory(JedisResourcePool jodisPool) {`
	`this.jodisPool=jodisPool;`
`}`
`@Override`
`public RedisConnection getConnection() {		`
	`return jodisPool.getResourceForSpringDataRedis();`
`}`
`@Override`
`public void destroy() throws Exception {`
	`if(jodisPool!=null)`
		`jodisPool.close();`
`}`
`@Override`
`public DataAccessException translateExceptionIfPossible(RuntimeException ex) {`
	`return EXCEPTION_TRANSLATION.translate(ex);`
`}	`
`@Override`
`public RedisClusterConnection getClusterConnection() {`
	`// TODO Auto-generated method stub`
	`return null;`
`}`
`@Override`
`public boolean getConvertPipelineAndTxResults() {`
	`// TODO Auto-generated method stub`
	`return false;`
`}`
`@Override`
`public RedisSentinelConnection getSentinelConnection() {`
	`// TODO Auto-generated method stub`
	`return null;`
`}	`
`@Override`
`public void afterPropertiesSet() throws Exception {`
	`// TODO Auto-generated method stub`
`}`

}

3. 在@configuration类里加注解初始化对应的类

    `@Bean`
`public JedisResourcePool jodisPool() {`
	`JedisPoolConfig jedisPoolConfig=new JedisPoolConfig();`
	`jedisPoolConfig.setMaxTotal(20);`
	`jedisPoolConfig.setMaxIdle(20);`
	`jedisPoolConfig.setMinIdle(5);`
	`jedisPoolConfig.setMaxWaitMillis(-1);`
	`return RoundRobinJedisPool.create().curatorClient("192.168.11.62:2181", 30000).zkProxyDir("/jodis/codis-demo").build();`
`}`
`@Bean`
`public JodisConnectionFactory redisConnectionFactory(){`
	`return new JodisConnectionFactory(jodisPool());`
`}`	
`@Bean`
`public RedisTemplate<Object, Object> redisTemplate(`
		`RedisConnectionFactory redisConnectionFactory)`
				`throws UnknownHostException {`
	`RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>();`
	`template.setConnectionFactory(redisConnectionFactory());`
	`return template;`
`}`
  1. @Autowired注入RedisTemplate就能使用了
Clone this wiki locally