2017-12-30 77 views
1

모바일 앱용 API를 제공하는 Symfony 기반 모바일 애플리케이션 및 서버를 보유하고 있습니다.Doctrine에서 교착 상태를 처리하는 방법은 무엇입니까?

나는 사용자가 Post을 좋아할 수있는 상황이 있습니다. Post과 같은 사용자가이 특정 사용자가 좋아하는 ManyToMany 테이블에 항목을 추가하면 Post (1 단계)입니다. 그러면 Post 테이블에서 likesCounter가 증가합니다 (2 단계). 그렇다면 User 테이블에서 나는 (사용자가 Post을 좋아했기 때문에) 사용자를위한 게임 포인트를 증가시킵니다 (3 단계).

많은 사용자가 동시에 Post을 좋아하고 교착 상태가 발생하는 상황이 있습니다 (Post 테이블 또는 User 테이블). 처리 방법 Doctrine Docs에서이 같은 솔루션을 볼 수

<?php 

try { 
    // process stuff 
} catch (\Doctrine\DBAL\Exception\RetryableException $e) { 
    // retry the processing 
} 

하지만 catch 부분에 어떻게해야합니까? 좋아하는 모든 프로세스 (예 : 1 ~ 3 단계)를 3 번 ​​시도하고 실패한 경우 BadRequest를 모바일 응용 프로그램으로 반환 하시겠습니까? 또는 다른 것?

이것이 좋은 예입니다. 어쩌면 제가 교착 상태가 일어나지 않도록 프로세스를 다시 만들 수 있었는지 모르겠지만 실제로 일어난다면 어떻게해야하는지 알고 싶습니다.

답변

0

내가 할 수있는 일은 모든 게시물을 대기열에 게시하고 batch consumer을 사용하여 소비하므로 단일 게시물에 업데이트를 그룹화 할 수 있습니다.

<?php 
 

 
for ($i = 0; $i < $retryCount; $i++) { 
 
    try { 
 
     // try updating 
 
     break; 
 
    } catch (\Doctrine\DBAL\Exception\RetryableException $e) { 
 
     // you could also add a delay here 
 
     continue; 
 
    } 
 
} 
 

 
if ($i === $retryCount) { 
 
    // throw BadRequest 
 
}

이것은 추한 솔루션이며 나는 그것을 제안하지 것이다 :

당신에게 현재의 구현을 유지 주장하는 경우에 당신은 당신 자신을 다음과 같이 제안 된 길을 갈 수있다. 교착 상태는 재 시도하거나 지연을 사용하여 "피할"수 없습니다. 또한 named locks을보고 동일한 재시도 시스템을 사용하지만 교착 상태가 발생할 때까지 기다리지 마십시오.

0

문제는 Symfony Entity Manager가 실패한 후에 db 연결을 닫고 ORMException을 잡아도 데이터베이스 작업을 계속할 수 없다는 것입니다.

첫 번째 좋은 해결책은 'likes'async를 rabbitmq 또는 다른 대기열 구현으로 처리하는 것입니다. 단계별

: {type: 'like', user:123, post: 456}

  • 에 게시처럼

    1. 메시지를 만들기 계산이 업데이트는 '좋아하는'소비.

    postId를 기반으로 잠금을 설정하려는 여러 소비자가있을 수 있습니다. 두 명의 소비자가 동일한 게시물을 업데이트하려고하면 그 중 하나가 잠금을 얻지 못할 것입니다. 그러나 괜찮습니다. 실패한 메시지를 소비 할 수 있습니다.

    두 번째 해결 방법은 특수 테이블을 갖는 것입니다. post_likes (userId, postId, timestamp). 엔드 포인트가이 테이블에서 새 행을 동 기적으로 작성할 수 있습니다. 그리고이 표를 사용하여 일부 게시물에서 '좋아요'를 셀 수 있습니다. 또는 cron 스크립트를 작성할 수 있습니다.이 스크립트는이 테이블의 게시물 수를 업데이트합니다.