Как использовать redis WATCH в Node.js? - PullRequest
0 голосов
/ 06 июня 2018

Фон

У меня атомарная операция, и мне нужно использовать блокировку, чтобы другие клиенты не могли прочитать нестабильное значение.

  • Платформа : узел 10.1.0
  • Библиотека : redis

Решение

Согласно официальной документации, решение для этого заключается в использовании WATCH вместе с MULTI:

Проблема

Теперь использование MULTI задокументировано, и у меня есть общее представление о том, как я могу его использовать.

var redis = require( "redis" );
var bluebird = require( "bluebird" );
var client = redis.createClient();
var multi = client.multi();

multi.hsetAsync( "test", "array", "[1, 2]" );
multi.hgetAsync( "test", "array" );
multi.execAsync( ).then( console.log ); // [ 0, "[1, 2]" ]

Я понимаю, что это правильная реализация multi.Сначала мне нужно для создания клиента, а затем я создаю мультизапрос.

Я понимаю, что multi и client используют один и тот же интерфейс, но также не ясно, чтоу меня есть преимущества (если есть) от использования hgetAsync вместо hget в запросе multi, так как я предполагаю, что все, что делает multi, - это добавление указанных запросов в очередь синхронно (поэтому мне не нужен вариант Async).

После вызова multi.execAsync( ) выполнение запроса произойдет атомарно .

Но я не понимаю, как WATCH предполагается вводить здесь.Я не смог найти ни одной ссылки на нее в документации, ничего, касающейся системы блокировки оптимиста, которую имеет REDIS.

Вопросы

Итак, у меня есть следующие вопросы:

  1. Поддерживается ли WATCH с MULTI?
  2. Если да, можете ли выподелиться фрагментом кода?
  3. Имеет ли смысл в этом примере использовать multi.hgetAsync( "test", "array" ); вместо multi.hget( "test", "array" );?

1 Ответ

0 голосов
/ 07 июня 2018

Asnwer

Нет документации относительно использования WATCH в node-redis.Однако я нашел чрезвычайно полезный набор советов в MDN:

https://developer.mozilla.org/en-US/docs/Mozilla/Redis_Tips

В целом, WATCH следует использовать следующим образом:

var redis  = require("redis"),
client = redis.createClient({ ... });

client.watch("foo", function( err ){
    if(err) throw err;

    client.get("foo", function(err, result) {
        if(err) throw err;

        // Process result
        // Heavy and time consuming operation here

        client.multi()
            .set("foo", "some heavy computation")
            .exec(function(err, results) {

                /**
                 * If err is null, it means Redis successfully attempted 
                 * the operation.
                 */ 
                if(err) throw err;

                /**
                 * If results === null, it means that a concurrent client
                 * changed the key while we were processing it and thus 
                 * the execution of the MULTI command was not performed.
                 * 
                 * NOTICE: Failing an execution of MULTI is not considered
                 * an error. So you will have err === null and results === null
                 */

            });
    });
});

Итак,чтобы ответить на мои вопросы:

  1. Да, хотя watch вызывается для прототипа RedisClient, а не для прототипа Multi.
  2. Фрагмент кода, представленный выше.
  3. Поскольку каждый метод из объекта, который имеет прототип Multi, возвращает сам объект, использование версий методов Async не дает никаких преимуществ, за исключением execAsync, который позволяет выполнять несколько запросов ииметь дело с ответом в Обещании вместо обратного вызова.

Важные замечания

Еще одна очень важная вещь заключается в том, что watch работает только для KEYS, не для хэшей .Так что в моем случае вы не можете наблюдать поле array хеша test.Вы можете просматривать весь набор test, но не конкретное поле.

Итак, потому что в моем коде я действительно хочу посмотреть поле в хэше.Это невозможно.Вместо этого я должен использовать систему именования ключей, которая вместо этого позволит:

var redis = require( "redis" );
var bluebird = require( "bluebird" );
var client = redis.createClient();
var multi = client.multi();

client.watchAsync( "test_array" )
    then( ( ) =>
        multi.set( "test_array", "[1, 2]" )
            .get( "test_array" )
            .execAsync( ) 
    )
    .then( console.log ); // [ 0, "[1, 2]" ]

Документация для этого очень скудна, но я надеюсь, что этот вопрос поможет кому-то в будущем.


Вы читаете это из будущего ?

Если вы читаете это из будущего, теперь вы можете насладиться моим личным вкладом в проект node_redis и проверить обновленную документацию:

...