Использовать многопоточность с redis, используя пул соединений jedis - PullRequest
0 голосов
/ 23 мая 2018

Я прочитал, что redis является однопоточным для пользователя / клиента.

Можно ли использовать пул соединений jedis для достижения многопоточного поведения?

В основном другой запрос клиента jedis будет использовать другое соединение, связанное с пулом подключения jedis, для запуска своих команд на один сервер redis.

Поскольку запросы клиента используют разные подключения, следовательно, один redis должен быть серверомнесколько запросов параллельно верно?

Ответы [ 3 ]

0 голосов
/ 23 мая 2018

Можно ли использовать пул соединений jedis для достижения многопоточного поведения?

Несмотря на то, что для связи с redis вы используете несколько соединений, потоков или обработку, все эти команды помещаются в одну очередь, и redis получит один за другим и выполнит один за другим. И каждая отдельная команда является атомарной.Так что это все еще однопотоковое поведение в аспекте redis.

Так как клиентские запросы используют разные соединения, следовательно, один redis должен параллельно обрабатывать несколько запросов на сервере, верно?

Не всегда команды от разных клиентов могут поступать в Redis в произвольном порядке, поэтому, если эти команды имеют какое-либо отношение к данным, могут произойти опасные вещи.

рассмотрим этот простой сценарий, если в Redis есть счетчик S, есливсе клиенты выполняют команду INCR, тогда все в порядке, потому что каждая команда выполняется атомарно, но если какой-то клиентский код похож на что-то, что:

s = get S
t = s + 10
set S t

Тогда все будет неправильно.И вы должны использовать команду Multi / exec, чтобы гарантировать, что несколько команд будут атомарными, а не только одна команда.Более подробную информацию о транзакциях в Redis можно найти на этой странице 1017 *.Подробно.

0 голосов
/ 23 мая 2018

Это прекрасно работает в моей (сетевой) многопоточной среде.

Убедитесь, что экземпляр RedisInterface является статическим в вашем классе.

public class RedisInterface implements Closeable
{   
/*      
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>   
*/

private JedisPool jedisPool =  null;

private synchronized void initializePool()
{
    if(jedisPool!=null) return;

    JedisPoolConfig poolConfig = new JedisPoolConfig();
    poolConfig.setMaxTotal(Integer.parseInt(AppConfig.REDIS_MAX_CONN)); //max conn count
    poolConfig.setMaxIdle(Integer.parseInt(AppConfig.REDIS_MAX_IDLE_CONN)); //max idle conn count
    poolConfig.setMaxWaitMillis(Long.parseLong(AppConfig.REDIS_MAX_WAIT_TIME)); // max wait time for new connection (before throwing exception)

    jedisPool = new JedisPool(poolConfig, 
            AppConfig.REDIS_IP, 
            Integer.parseInt(AppConfig.REDIS_PORT),
            Integer.parseInt(AppConfig.REDIS_CONN_TIMEOUT));

}

//not synchronized after testing thread safety of jedisPool.getResource()
protected Jedis getJedis()
{               
    if(jedisPool==null)
        initializePool();

      Jedis jedis = jedisPool.getResource();

      return jedis;     
}


public Long set(final byte[] key, final byte[] field, final byte[] value)
{
    Jedis redis = null; 
    Long ret =0L;

    try
    {
        redis = getJedis();

        ret = redis.hset(key, field, value);            
        redis.expire(key, Integer.parseInt(AppConfig.REDIS_EXPIRE_MIN)*60); //      
    }
    finally
    {
        if(redis!=null)         
            redis.close();
    }

    return ret;
}

public byte[] get(final byte[] key, final byte[] field) {

    Jedis redis = null ;
    byte[] valueBytes = null;

    try
    {
        redis = getJedis();

        valueBytes = redis.hget(key, field);
    }
    finally
    {       
        if(redis!=null)             
            redis.close();
    }

    return valueBytes;

}

@Override
public void close() throws IOException {

    if(jedisPool!=null)     
        jedisPool.close();      
}

}
0 голосов
/ 23 мая 2018

Я ответил на аналогичный вопрос здесь , вы можете проверить его для деталей.

TL / DR : Redis все еще будет однопоточным, но в целомНа схеме вещей время, используемое Redis для ответа, на порядок меньше времени, используемого сетью.Вы получите выгоду от многопоточности, да.

РЕДАКТИРОВАТЬ: Вдоль конвейера запросов у вас будет 3 точки, где запросы обрабатываются последовательно.Это когда пакеты данных отправляются через провод (у вас есть только один провод, но пакеты из разных запросов будут смешаны) вперед и назад, и когда Redis обслуживает ваш запрос.Но сам Редис тоже не тупой.Ваши запросы будут поступать из сетевого сокета и будут предварительно обработаны и записаны в клиентские буферы.Эта часть обрабатывается параллельно.Затем основной цикл Redis выберет ваши команды из очереди, обработает и запишет ответ в клиентские буферы.Эта часть делается последовательно.Затем ответы от клиентских буферов будут упакованы и отправлены вам по телеграфу.Это также делается параллельно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...