2014-02-09 5 views
3

RetwisJ 자습서를 사용할 수 있습니다. here. 여기서 나는 Redis 트랜잭션이 구현되지 않는다고 생각합니다. 예를 들어 다음 함수에서 일부 예외가 발생하면 데이터가 일관성없는 상태로 유지됩니다. 나는 다음과 같은 기능이 단일 트랜잭션으로 봄 데이터 레디 스에서 구현 될 수있는 방법을 알고 싶어요 :스프링 데이터 Redis에서 트랜잭션을 구현하는 방법은 무엇입니까?

여기 userIdCounter, valueOpsusers
public String addUser(String name, String password) { 
     String uid = String.valueOf(userIdCounter.incrementAndGet()); 

     // save user as hash 
     // uid -> user 
     BoundHashOperations<String, String, String> userOps = template.boundHashOps(KeyUtils.uid(uid)); 
     userOps.put("name", name); 
     userOps.put("pass", password); 
     valueOps.set(KeyUtils.user(name), uid); 

     users.addFirst(name); 
     return addAuth(name); 
    } 

은 생성자에서 초기화됩니다. 나는 문서 (섹션 4.8)에서 this을 보았지만, 함수 밖에서 어떤 변수가 초기화되는이 함수에 어떻게 맞는지 알아낼 수 없다. (각각의 변수를 초기화해야한다고 말하지 말아라. 거래가 필요한 모든 기능!).

PS : 스프링 데이터 Redis에는 어떤 @Transaction 주석 또는 트랜잭션 관리자가 있습니까?

업데이트 :MULTI, EXEC을 사용해 보았습니다. 내가 작성한 코드는 다른 프로젝트를 위해,하지만이 문제에 적용 할 때 그 다음이 있습니다 :

public String addMyUser(String name, String password) { 
     String uid = String.valueOf(userIdCounter.incrementAndGet()); 
     template.execute(new SessionCallback<Object>() { 
      @Override 
      public <K, V> Object execute(RedisOperations<K, V> operations) 
        throws DataAccessException { 
       operations.multi(); 
       getUserOps(operations, KeyUtils.uid(uid)).put("name", name); 
       getUserOps(operations, KeyUtils.uid(uid)).put("pass", password); 
       getValueOps(operations).set(KeyUtils.user(name), uid); 
       getUserList(operations, KeyUtils.users()).leftPush(name); 
       operations.exec(); 
       return null; 
      } 
     }); 
     return addAuth(name); 
    } 
    private ValueOperations<String, String> getValueOps(RedisOperations operations) { 
     return operations.opsForValue(); 
    } 
    private BoundHashOperations<String, String, String> getUserOps(RedisOperations operations, String key) { 
     return operations.boundHashOps(key); 
    } 
    private BoundListOperations<String, String> getUserList(RedisOperations operations, String key) { 
     return operations.boundListOps(key); 
    } 

MULTI를 사용하는이 방법은, EXEC 권장할지 여부를 알려주세요.

답변

1

SD 레디 스 1.2까지 당신은 다음과 같은 것을 볼 수 있었다 위 TransactionSynchronisationManager

snipplet를 사용하여 자신을 처리 tansaction 알아서해야합니다 :

public String addUser(String name, String password) { 

    String uid = String.valueOf(userIdCounter.incrementAndGet()); 

    // start the transaction 
    template.multi(); 

    // register synchronisation 
    if(TransactionSynchronisationManager.isActualTransactionActive()) { 
     TransactionSynchronisationManager.registerSynchronisation(new TransactionSynchronizationAdapter()) { 

      @Override 
      public void afterCompletion(int status) { 
       switch(status) { 
        case STATUS_COMMITTED : template.exec(); break; 
        case STATUS_ROLLED_BACK : template.discard(); break; 
        default : template.discard(); 
       } 
      } 
     } 
    } 

    BoundHashOperations<String, String, String> userOps = template.boundHashOps(KeyUtils.uid(uid)); 
    userOps.put("name", name); 
    userOps.put("pass", password); 
    valueOps.set(KeyUtils.user(name), uid); 

    users.addFirst(name); 

    return addAuth(name); 
} 

번 멀티에 유의하시기 바랍니다을 읽고 작업도 트랜잭션의 일부가되므로 Redis 서버에서 데이터를 읽을 수 없을 수도 있습니다. WATCH을 추가로 호출 할 수 있으므로 위의 설정과 다를 수 있습니다. 더 나아가 복수의 콜백도 처리해야합니다. MULTI 및/또는 EXEC을 두 번 이상 보내지 마십시오.

곧 출시 될 Spring Data Redis 릴리스는 MULTi|EXEC|DISCARD을 처리하고 트랜잭션 동기화가 활성화되어있는 동안 기존의 키에 대한 읽기 작업을 허용하는 스프링 관리 트랜잭션을 지원합니다. BUILD-SNAPSHOT에 이미 회전을 부여하고 template.setEnableTransactionSupport(true)으로 설정하여이 기능을 사용할 수 있습니다.

+0

안녕하십니까. 오랜 시간이 걸렸습니다. 아무도 대답하지 못했기 때문에 어떻게해야 하는지를 알아 냈습니다 (질문에 업데이트되었습니다). 그러나 이것이 이것이 권장되는 방법인지는 모르겠습니다. TransactionSynchronisationManager를 사용할 수 있습니까? 이것 이외의 추가 구성이 필요합니까? 필자가 작성한 코드에서 발견 한 이점은 Redis에서 데이터를 읽어야 할 경우 '템플릿'을 사용할 수 있으므로 트랜잭션의 일부가 아니기 때문입니다. – sinu

+1

'SessionCallback' 사용은 완벽하게 [참조] (http://docs.spring.io/spring-data/data-redis/docs/current/reference/html/redis.html#tx)) 명령이 걸리는 시간 동안 사용 된 연결을 바인드하므로 나중에 실행하고 해제합니다. 'TransactionSynchronisationManager' 또는 다음 버전 1.3의'template.setEnableTransactionSupport (true)'는 진행중인 외부 트랜잭션이 활성화되어있을 때 밀접하게 위치하지 않는 여러 redis 호출을 처리하기위한 것입니다.일반적으로 TSM과 직접 상호 작용할 필요는 없습니다. –

관련 문제