Redis-Py часы хэш-ключ - PullRequest
       4

Redis-Py часы хэш-ключ

3 голосов
/ 05 февраля 2012

Я использую redis-py для взаимодействия с redis через python.Я нахожусь в ситуации, когда мне нужно атомарно обновить хеш-ключ, но сначала нужно получить значение по этому ключу, прежде чем я смогу его обновить.Просматривая документацию, кажется, что я могу использовать конвейер и команду WATCH, чтобы определить, когда ключ изменился.Есть ли способ посмотреть ключ внутри хеша?или это работает только для особых ключей?

Ответы [ 2 ]

2 голосов
/ 13 марта 2014

Вы не можете смотреть ключи хеша напрямую, пока это не поддерживается Redis.Но вы можете использовать дополнительные строковые ключи «блокировки» и определить контракт, по которому любой, кто изменяет ваши значения хеш-функции, должен выполнить следующую процедуру для любого хэш-ключа K:

  1. WATCH lock:K
  2. HGET K, сохранить текущее значение
  3. Start MULTI.
  4. SET lock:K ""
  5. HSET K updated_value
  6. EXEC

Это гарантирует, что обновленное значение хэша не будет перезаписано одновременно.

Хотя это вопрос Python, я предоставляю функцию NodeJS, которая реализует приведенный выше контракт (просто чтобы показать идею):

/**
 * Concurrently updates Redis string and hash value under the specified key.
 *
 * @param redisCli Redis client.
 * @param hashName Hash name.
 * @param objId Object ID.
 * @param transFun Cache object transformation function (i.e. a modification that we need to apply).
 * @param cbFun Callback function, to which a modified object is passed in case of success.
 */
exports.redisUpdateHashConcurrently = function(redisCli, hashName, objId, transFun, cbFun) {
    var lockKey = hashName + ':' + objId + ':lock';

    redisCli.watch(lockKey); // Step 1.

    redisCli.hget(hashName, objId, function(err, obj) { // Step 2.
        if (err) {
            redisCli.unwatch();

            cbFun && cbFun(undefined, err);

            return;
        }

        if (obj) {
            var modObj = transFun(JSON.parse(obj));
            var value = JSON.stringify(modObj);

            redisCli.multi() // Step 3.
                .set(lockKey, '') // Step 4.
                .expire(lockKey, 3)
                .hset(hashName, objId, value) // Step 5.
                .exec(function(err, replies) { // Step 6.
                    if (!replies) { // Object was modified by someone else, retry.
                        exports.redisUpdateHashConcurrently(redisCli, hashName, objId, transFun, cbFun);
                    }
                    else { // We have succeeded.
                        cbFun && cbFun(modObj, undefined);
                    }
                });
        }
        else {
            redisCli.unwatch();
        }
    });
};

Обратите внимание, что вы можете указать TTL для своего "заблокировать »ключи, чтобы они в конечном итоге были удалены.

0 голосов
/ 06 февраля 2012

Как насчет использования MULTI ?Тогда вам не нужно беспокоиться о просмотре ключа внутри хеша (который WATCH не поддерживает, как вы предложили).

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