2012-02-05 5 views
3

私はredis-pyを使用して、pythonを介してredisに接続しています。私はハッシュ・キーを原子的に更新する必要があるが、更新する前にまずそのキーの値を取得する必要がある状況にある。ドキュメントを見ると、パイプラインとWATCHコマンドを使用してキーがいつ変更されたかを判断できるようです。とにかくハッシュの内部にキーを見ることはありますか?またはこれは単一キーに対してのみ機能しますか?redis-pyウォッチハッシュキー

+0

こんにちは、どんな解決策ですか?私は原子的にも特定のハッシュキーの値を更新する必要があります...ハッシュ全体はおそらく見ることができますが、競合状態は非常に頻繁に発生します。 – geronime

+0

特異キーの場合、私はWATCHとMULTIによってそれを行うことができます。しかし、私はまた、ハッシュキー内でWATCHキーを達成しようとしています。 –

答えて

0

MULTIはどうですか?次に、ハッシュの内部でキーを見ることについて心配する必要はありません(あなたが示唆したように、ウォッチはサポートされていないようです)。

+0

MULTIでは、値を取得し、変更して値を戻すことができないように見えます。私が誤っていない限り、MULTIはコマンドをキューに入れるだけです。 – whatWhat

1

ハッシュキーを直接見ることはできませんが、これは現在Redisではサポートされていません。しかし、あなたは文字列キーを「ロック」の追加を使用して、あなたのハッシュ値を変更し、誰もが、Kキー任意のハッシュについては、以下の手順に従うべきで契約を定義することができます。

  1. WATCH lock:K
  2. HGET K 、現在の値を保存
  3. MULTIを開始します。
  4. SET lock:K ""
  5. EXEC

このupdated_value

  • HSET Kは、更新されたハッシュ値が同時に上書きされないことを保証します。

    これはPythonの質問ですが、私は(ちょうど考えを示すために)上の契約を実装NodeJS機能を提供します。あなたはあなたの「ロック」キーのTTLを指定することができ

    /** 
    * 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(); 
         } 
        }); 
    }; 
    

    注意、それらは最終的に除去される。