2015-04-09 8 views
2

Ниже мое Jedis CONFIGRedis весной данные рабовладелец конфигурация

@Bean 
public JedisConnectionFactory getJedisConnectionFactory() { 
    JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(); 
    jedisConnectionFactory.setUsePool(true); 
    return jedisConnectionFactory; 
} 

@Bean 
public RedisTemplate<String, Object> getRedisTemplate() { 
    RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>(); 
    redisTemplate.setConnectionFactory(getJedisConnectionFactory()); 
    return redisTemplate; 
} 

Эта конфигурация хорошо работает, когда у меня есть один сервер. То, что я хочу сделать, это иметь 1 redis master и несколько redis slaves. Для документации по redis чтение должно происходить от подчиненных, и запись должна выполняться от мастера. Как изменить конфигурацию для использования мастера для записи и ведомого для чтения?

Допустим, что мой мастер находится на уровне 192.168.10.10, а подчиненный - на локальном хосте.

Спасибо!

ответ

5

В настоящее время в Spring Data Redis отсутствует опция конфигурации, которая обеспечивала бы желаемое поведение. Также Jedis предлагают поддержку для такого сценария (см. jedis #458). RedisConnection запрашивает соединение с заводом при выполнении операций. На этом этапе цель использования запрошенного ресурса неясна, так как команда может быть r, w или rw.

Одним из возможных решений может быть пользовательский RedisConnectionFactory, способный обеспечить соединение - с одним из подчиненных вам - в случае выполнения команды readonly.

SlaveAwareJedisConnectionFactory factory = new SlaveAwareJedisConnectionFactory(); 
factory.afterPropertiesSet(); 

RedisConnection connection = factory.getConnection(); 

// writes to master 
connection.set("foo".getBytes(), "bar".getBytes()); 

// reads from slave 
connection.get("foo".getBytes()); 

/** 
* SlaveAwareJedisConnectionFactory wraps JedisConnection with a proy that delegates readonly commands to slaves. 
*/ 
class SlaveAwareJedisConnectionFactory extends JedisConnectionFactory { 

    /** 
    * Get a proxied connection to Redis capable of sending 
    * readonly commands to a slave node 
    */ 
    public JedisConnection getConnection() { 

    JedisConnection c = super.getConnection(); 

    ProxyFactory proxyFactory = new ProxyFactory(c); 
    proxyFactory.addAdvice(new ConnectionSplittingInterceptor(this)); 
    proxyFactory.setProxyTargetClass(true); 

    return JedisConnection.class.cast(proxyFactory.getProxy()); 
    }; 

    /** 
    * This one will get the connection to one of the slaves to read from there 
    * 
    * @return 
    */ 
    public RedisConnection getSlaveConnection() { 

    //TODO: find the an available slave serving the data 
    return new JedisConnection(new Jedis("your slave host lookup here")); 
    } 

    static class ConnectionSplittingInterceptor implements MethodInterceptor, 
     org.springframework.cglib.proxy.MethodInterceptor { 

    private final SlaveAwareJedisConnectionFactory factory; 

    public ConnectionSplittingInterceptor(SlaveAwareJedisConnectionFactory factory) { 
     this.factory = factory; 
    } 

    @Override 
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { 

     RedisCommand commandToExecute = RedisCommand.failsafeCommandLookup(method.getName()); 

     if (!commandToExecute.isReadonly()) { 
     return invoke(method, obj, args); 
     } 

     RedisConnection connection = factory.getSlaveConnection(); 

     try { 
     return invoke(method, connection, args); 
     } finally { 
     // properly close the connection after executing command 
     if (!connection.isClosed()) { 
      connection.close(); 
     } 
     } 
    } 

    private Object invoke(Method method, Object target, Object[] args) throws Throwable { 

     try { 
     return method.invoke(target, args); 
     } catch (InvocationTargetException e) { 
     throw e.getCause(); 
     } 
    } 

    @Override 
    public Object invoke(MethodInvocation invocation) throws Throwable { 
     return intercept(invocation.getThis(), invocation.getMethod(), invocation.getArguments(), null); 
    } 
    } 
} 

В решении выше содержатся проблемы с сервером. Например. MULTIEXEC блоки в вашем приложении могут перестать работать так, как ожидалось, так как команды теперь потенциально могут быть переданы туда, где вы не хотите, чтобы они были. Так что, возможно, имеет смысл иметь несколько RedisTemplates для выделенных читать, написать цель.

+0

как около двух двух Jedis подключения заводов и два шаблона redis, один для чтения, а другой для записи? Будет ли это работать (теоретически)? – riship89

+1

да 2 фабрики и шаблоны будут работать. –

+0

alrighty! благодаря! – riship89

0

Вы должны использовать Redis Sentinel, чтобы сохранить конфигурацию ведущий/ведомый Redis ... Вы можете использовать ниже для подключения к дозорного бассейн-

@Bean 
public RedisConnectionFactory jedisConnectionFactory() { 
RedisSentinelConfiguration sentinelConfig = new RedisSentinelConfiguration() .master("mymaster") 
    .sentinel("127.0.0.1", 26379) .sentinel("127.0.0.1", 26380); 
return new JedisConnectionFactory(sentinelConfig); 
} 

ссылка: Spring Sentinel support

Смежные вопросы