Node-redis: Конвейерная обработка

Созданный на 13 янв. 2014  ·  9Комментарии  ·  Источник: NodeRedis/node-redis

Привет, народ,

как программно включить конвейерную обработку в node_redis?

Я видел документацию, в которой говорится, что в большинстве случаев это происходит автоматически, и я хочу понять, есть ли способ принудительно принудительно использовать это из кода приложения в node_redis

[ ec2-user @ DevOps ~] $ redis-benchmark -n 100000 -t set, получить -P 16 -q -h 10.0.1.10
НАБОР: 199600.80 запросов в секунду
GET: 193050,19 запросов в секунду

[ ec2-user @ DevOps ~] $ redis-benchmark -n 100000 -t set, получить -q -h 10.0.1.12
НАБОР: 14098,41 запросов в секунду
GET: 13743,82 запроса в секунду

на узле Redis разница более чем в 10 раз.

Благодарность,
Дмитрий

Feature Request fixed / done

Самый полезный комментарий

Все команды отправляются «конвейерно», но они никогда не будут отправлены в одном кадре записи конвейера по одной или двум причинам:

  1. Обратный вызов для sismember - это то, что вызывает вызов hgetall, поэтому вы неявно предотвращаете конвейерную обработку этих команд для любого данного вызова sismember. Обратный вызов не вызывается, пока Redis не ответит.
  2. Если base и client - разные клиенты Redis, они НИКОГДА не могут использовать один и тот же конвейер.

Команды должны выполняться из одного и того же контекста *, чтобы увидеть какие-либо преимущества конвейерной обработки. Например, аналогично примеру PING в документации по конвейерной обработке Redis:

// These commands will all be pipelined together:
client.ping()
client.ping()
client.ping()
client.ping(function () {
  // This would *NEVER* be in the same pipeline frame as the other four because it requires a reply to be received first
  client.ping()
})

* или из разных контекстов, если отправлено быстрее, чем Redis отвечает, но никогда не отвечает в зависимых контекстах

Все 9 Комментарий

Это делается с помощью команд client.multi и multi.exec?

Привет @saritasa - конвейерная обработка автоматическая. Это всегда происходит внутри клиента. Вам не нужно использовать multi или exec, чтобы включить его.

Привет Брайс,

  1. Я запутался, а зачем тогда "мульти" функции внутри node_redis?
  2. Какой алгоритм используется для автоматического конвейера команд?

Благодарность,
Дмитрий

Множественные операции взяты из спецификации протокола Redis, они имеют транзакционную цель за пределами конвейерной обработки: http://redis.io/commands/multi

С точки зрения того, как работает конвейерная обработка: http://redis.io/topics/pipelining, это просто вопрос того, что клиент пишет команды в Redis так же быстро, как вы их отправляете, не дожидаясь ответа, прежде чем писать следующую. Клиент отслеживает отправленные команды, а затем совмещает ответы с отправленными командами после ответа Redis.

Спасибо, Брайс, я понимаю, как работает http://redis.io/topics/pipelining . в приложении node.js - как должен быть структурирован код, чтобы запросы были конвейерными?

так что в примере ниже

hgetall & expire - конвейерные или нет? Один из вызовов - внутренний обратный вызов.


function getByID (table, id, next) {
если (! успех) return setTimeout (function () {
getByID (таблица, идентификатор, следующий);
}, 2000);

var end = utils.getEndTime(),
    base = getBase(),
    client = getClient(PK2str(table, id)),
    key = getHashID(table, id);

base.sismember(table, key, function (err, val) {
    if (err || !val) return next();

    client.hgetall(key, function (err, val) {
        if (err || !val) return next(new Error('Expired'), id);

        val = arrays_parse(table, val);
        next(null, val);
        client.expire(key, cfg.ttl.shards);

        if (!exports.silent) {
            profiler.log('cache', {
                'table': table,
                'id': key,
                'method': 'getByID',
                'data': val,
                'time': end()
            });
        }
    });  
});

}

Все команды отправляются «конвейерно», но они никогда не будут отправлены в одном кадре записи конвейера по одной или двум причинам:

  1. Обратный вызов для sismember - это то, что вызывает вызов hgetall, поэтому вы неявно предотвращаете конвейерную обработку этих команд для любого данного вызова sismember. Обратный вызов не вызывается, пока Redis не ответит.
  2. Если base и client - разные клиенты Redis, они НИКОГДА не могут использовать один и тот же конвейер.

Команды должны выполняться из одного и того же контекста *, чтобы увидеть какие-либо преимущества конвейерной обработки. Например, аналогично примеру PING в документации по конвейерной обработке Redis:

// These commands will all be pipelined together:
client.ping()
client.ping()
client.ping()
client.ping(function () {
  // This would *NEVER* be in the same pipeline frame as the other four because it requires a reply to be received first
  client.ping()
})

* или из разных контекстов, если отправлено быстрее, чем Redis отвечает, но никогда не отвечает в зависимых контекстах

получил сейчас - спасибо! Это очень ценный комментарий!

Я думаю, что node_redis «автоматическая конвейерная обработка» - это не конвейерная обработка, на которую ссылается официальный redis.

Это время называется RTT (время туда и обратно). Очень легко увидеть, как это может повлиять на производительность, когда клиенту необходимо выполнить множество запросов подряд (например, добавить много элементов в один и тот же список или заполнить базу данных множеством ключей). Например, если время RTT составляет 250 миллисекунд (в случае очень медленного соединения через Интернет), даже если сервер способен обрабатывать 100 тысяч запросов в секунду, мы сможем обрабатывать максимум четыре запроса в секунду.
Если используемый интерфейс является интерфейсом с обратной связью, RTT намного короче (например, мой хост сообщает о 0,044 миллисекундах пинг 127.0.0.1), но это все равно много, если вам нужно выполнить много записей подряд.

Конвейерная обработка с помощью официального redis означает объединение нескольких команд и их однократную отправку для противодействия задержке из-за RTT, которая не обрабатывается node_redis. А «автоматическая конвейерная обработка» в node_redis фактически отправляет как можно больше команд одновременно с использованием модели асинхронного программирования Node.

Вот хорошая статья, в которой обсуждается этот вопрос. http://informatikr.com/2012/redis-pipelining.html

@Vizwind @saritasa и .multi, и .batch используют конвейерную обработку, как это предполагалось начиная с версии 2.2.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги