java – spring data redis master slave config

Here is my jedis configuration

@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;
}

This configuration works well when I have a single server What I want to do is to have one redis master and multiple redis slave According to redis documents, reads should occur from slave and writes should occur from master How do I change the above configuration to use master for writing and slave for reading?

It can be said that my master is at 192.168 10.10, slave in localhost

thank you!

Solution

At present, there are no configuration options in spring data redis that can realize the required behavior Jedis also did not support this situation (see jedis #458)

One possible solution is to customize redisconnectionfactory, which can provide connection - a slave device you own when you execute read-only commands

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);
    }
  }
}

The above solution has several problems For example Multiple exec blocks in your application may no longer work as expected because commands may now be sent somewhere you don't want them Therefore, it may make sense to use multiple redistemplates for dedicated read and write purposes

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>