2012-02-05 3 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. 시계 lock:K
  2. HGET K를 , 현재 값 저장
  3. MULTI를 시작하십시오.
  4. SET lock:K ""
  5. EXEC

이 updated_value

  • HSET K는 업데이트 된 해시 값이 동시에 덮어 쓰기되지 않는다는 것을 보장합니다. ,

    /** 
    * 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을 지정할 수 있습니다 : 이것은 파이썬 질문이지만

    , 나는 (단지 아이디어를 보여주기 위해) 위 계약을 구현하는 NodeJS 기능을 제공 그래서 그들은 결국 제거됩니다.