redis-py手表哈希密钥

时间:2012-02-05 00:15:55

标签: python redis

我正在使用redis-py通过python与redis连接。我正处于需要以原子方式更新散列键的情况,但首先需要在更新之前检索该键的值。查看文档,看起来我可以使用管道和WATCH命令来确定密钥何时发生了变化。无论如何都要在哈希中看一个键?或者这只适用于单数键?

2 个答案:

答案 0 :(得分:2)

您无法直接观看哈希键,Redis目前不支持此功能。但你可以使用额外的"锁定"字符串键,并定义一个契约,修改哈希值的任何人都应该遵循以下过程来处理任何哈希键K

  1. 观看lock:K
  2. HGET K,保存当前值
  3. 启动MULTI。
  4. 设置lock:K""
  5. HSET K updated_value
  6. EXEC
  7. 这将保证不会同时覆盖更新的哈希值。

    虽然这是一个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。密钥,以便最终将其删除。

答案 1 :(得分:0)

如何使用MULTI?然后你不必担心在哈希中看到一个键(WATCH看起来不像你建议的那样支持)。