Является ли плохой практикой передавать экземпляр jedis между методами?

Я имел в виду этот SO вопрос и сделал несколько дополнений в этом тесте производительности. Основная проблема заключается в том, что мой API становится медленным по мере увеличения нагрузки на сервер. Я использую конфигурацию пула jedis.

// get a new instance
    public synchronized Jedis getJedi() {
    try {
        return jedisPool.getResource();
    } catch (Exception e) {
        log.fatal("REDIS CONN ERR:", e);
        return null;
    }
    }

// intialize at start
    public void initialize() {
    if (jedisPool == null) {
        IniUtils cp = PropertyReader.getConnPoolIni();

        String host = cp.get(REDIS, REDIS_HOST);
        int port = Integer.parseInt(cp.get(REDIS, REDIS_PORT));
        String password = cp.get(REDIS, REDIS_PASSWORD);
        int timeout = Integer.parseInt(cp.get(REDIS, REDIS_TIMEOUT));

        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(Integer.parseInt(cp.get(REDIS, REDIS_MAX_TOTAL_CONNECTIONS)));
        poolConfig.setMaxIdle(Integer.parseInt(cp.get(REDIS, REDIS_MAX_IDLE)));
        poolConfig.setMinIdle(Integer.parseInt(cp.get(REDIS, REDIS_MIN_IDLE)));
        poolConfig.setMaxWaitMillis(Long.parseLong(cp.get(REDIS, REDIS_MAX_WAIT_TIME_MILLIS)));

        poolConfig.setTestOnBorrow(true);
        poolConfig.setTestOnReturn(true);
        poolConfig.setTestWhileIdle(true);

        if (password != null && !password.trim().isEmpty()) {
        jedisPool = new JedisPool(poolConfig, host, port, timeout, password);
        } else {
        jedisPool = new JedisPool(poolConfig, host, port, timeout);
        }

        test();

      }
    }

    @Override
    public void destroy() {
      if (jedisPool.isClosed() == false)
          jedisPool.destroy();
    }

    private void test() {
      try (Jedis test = getJedi()) {
        log.info("Testing Redis:" + test.ping());
      }
    }

И во время использования я получаю экземпляр Jedis в try-with-resources и работаю над ним. Я использую очень мало конвейерной обработки, и существуют различные вызовы Redis, поэтому каждый раз при вызове метода создается новый экземпляр jedis.

Согласно общему вопросу SO, моя реализация приведет к очень медленным результатам. Итак, могу ли я передать экземпляр Jedis методам и работать с конвейером в соответствии с бизнес-логикой. Что-то вроде этого -

  public void push5(int n) {
    try (Jedis jedi = redisFactory.getJedi()) {
        pushWithResource(n, jedi, 0);
    }
  }

  public void pushWithResourceAndPipe(int n, Jedis jedi, int k) {
    if (k >= n)
        return;
    Pipeline pipeline = jedi.pipelined();
    map.put("id", "" + i);
    map.put("name", "lyj" + i);
    pipeline.hmset("m" + i, map);
    ++i;
    pushWithResourceAndPipe(n, jedi, ++k);
    pipeline.sync();
  }

    public void pushWithResource(int n, Jedis jedi, int k) {
    if (k >= n)
        return;
    map.put("id", "" + i);
    map.put("name", "lyj" + i);
    jedi.hmset("m" + i, map);
    ++i;
    pushWithResource(n, jedi, ++k);
  }

Есть ли способ улучшить вызовы API? Не могли бы вы порекомендовать некоторые проекты, которые используют jedis на стороне сервера, чтобы я лучше понял, как эффективно использовать jedis.

Конфигурация Redis/Jedis

Версия Jedis: 2.8.1 Версия Redis: 2.8.4 Версия Java: 1.8


person theGamblerRises    schedule 21.11.2016    source источник


Ответы (1)


  1. getJedi не нужно «синхронизировать», так как JedisPool является потокобезопасным.
  2. Если ваша логика допускает добавление задержки из setTestOnBorrow, вы можете отключить другие вещи (setTestOnReturn, setTestWhileIdle). Если ваша логика допускает повторные попытки, отключение setTestOnBorrow должно помочь. (поскольку он всегда выполняет проверку пинг-понга для каждого заимствования)
  3. В вашем pushWithResourceAndPipe есть ошибка: вы создаете экземпляр конвейера для каждого рекурсивного вызова, который может быть «медленнее», чем pushWithResource. Я думаю, вы намеревались добавить все запросы в один конвейер и синхронизировать, а затем вам нужно передать экземпляр конвейера и вызвать синхронизацию от вызывающей стороны.
person Jungtaek Lim    schedule 25.01.2017