2014-05-09 1 views
7

개발중인 게임에서 경쟁 조건을 피하기 위해 Django 1.6 트랜잭션을 사용하려고합니다. 게임 서버는 2 명의 플레이어를 짝 지어주는 하나의 간단한 목표를 가지고 있습니다.Django 1.6 트랜잭션이 경쟁 조건을 피하기 위해

내 현재의 접근 방식은 다음과 같습니다

  1. 사용자는 게임을 기다리는 다른 사람이있는 경우
  2. 서버 점검을 놀고 싶어.
    1. 이 아닌 경우 GameConnection 개체 (고유 식별자 -uuid4)가 생성됩니다.
    2. 이면 GameConnection 식별자를 가져와 GameConnection을 삭제합니다.

      # data['nickname'] = user's choice 
      games = GameConnection.objects.all() 
      if not games: 
          game = GameConnection.objects.create(connection=unicode(uuid.uuid4())) 
          game.nick1 = data["nickname"] 
          game.save() 
      
          response = HttpResponse(json.dumps({'connectionId': game.connection, 'whoAmI': 1, 'nick1': game.nick1, 'nick2': ""})) 
      else: 
          game = games[0] 
          conn = game.connection 
          nick1 = game.nick1 
          nick2 = data["nickname"] 
          game.delete() 
          response = HttpResponse(json.dumps({'connectionId': conn, 'whoAmI': 2, 'nick1': nick1, 'nick2': nick2})) 
      
      return response 
      

      은 물론 위의 코드에서 경쟁 조건이 있습니다 :

이는 코드입니다. 이 코드는 원 자성이 아니므로 다음과 같이 발생할 수 있습니다.

  • 게임 연결을 확인합니다. 찾지 못합니다.
  • A 게임 연결을 만듭니다.
  • B 게임 연결을 확인합니다. 하나 (A)를 찾습니다.
  • C 게임 연결을 확인합니다. 하나 (A)를 찾습니다.
  • B는 A의 연결 식별자를 가져와 게임을 시작합니다.
  • C가 A의 연결 식별자를 가져와 게임을 시작합니다.

나는이 전체 블록을 with transaction.atomic(): 아래에서 시도했거나 @transaction.atomic 데코레이터를 사용했습니다. 하지만 여전히 경쟁 조건을 재현 할 수 있습니다.

여기에 누락 된 트랜잭션 동역학에 대한 정보가있을 것입니다. 누구든지 빛을 흘릴 수 있습니까?

+0

저는 전문가는 아니지만 제 이해에 따라 원자 트랜잭션이 쓰기에 적용됩니다. 귀하의 경우에는 한 번에 한 쌍의 페어링 만 발생하도록하기 위해 일종의 뮤텍스 잠금을 사용하려고 할 수 있습니다. 이것은 Java에서 @synchronized와 유사합니다. 그래도 모든 성능면에서 효율적이지는 않습니다. –

답변

2

@Sai는 트랙에 있습니다 ... 핵심은 잠금/뮤텍스가 쓰기 (또는 삭제) 때까지 발생하지 않는다는 것입니다. 코딩 된대로 보류중인 연결의 "검색"(읽기)과 보류중인 연결의 "클레임"(쓰기/잠금) 사이에 항상 시간이 있으며 연결이 요청되는 과정에 있음을 알 수 없습니다.

당신은 PostgreSQL을를 사용하는 경우, 당신은 트랜잭션이 완료 될 때까지 동일한 행을 얻기에서 다른 요청을 방지 할 수 있습니다 "업데이트 선택"으로 잠금을 강제 할 수 있습니다 (MySQL은도 지원하는 확신) :

game = GameConnection.objects.all()[:1].select_for_update() 
if game: 
    #do something, update, delete, etc. 
else: 
    #create 

최종 메모 - all() 이외의 다른 게임을 선택하면 게임을 선택할 수 있습니다 (예 : '생성 된'타임 스탬프 등). 희망이 도움이됩니다.

관련 문제