2014-02-09 2 views
1

x 초 단위로 실행하는 cron 작업이 n 개 서버에 있습니다. "SELECT FROM table WHERE time_scheduled < CURRENT_TIME"이 결과 집합에 대해 긴 작업을 수행합니다.동일한 결과를 반환하지 않으려면 SELECT + UPDATE

내 문제는 지금 : 두 개의 별도 서버가 동시에 같은 작업을 수행하는 것을 피하려면 어떻게합니까?

아이디어는 * time_scheduled *를 선택한 후 설정된 간격으로 업데이트하는 것입니다. 그러나 두 서버가 동시에 쿼리를 실행하면 너무 늦을 수 있습니다.

모든 아이디어를 환영합니다. 그것은 엄격한 MySQL 솔루션이 될 필요가 없습니다.

감사합니다.

+0

mysql 서버가 모든 서버에서 공유됩니까? – user4035

+0

예, 모두 동일한 서버에서 가져옵니다. – fandangosoeren

답변

0

하나의 MySQL 인스턴스가 있고이 처리 작업을 실행하기 위해 n 서버의 연결을 추측하고 있습니다. 여기에 작업 대기열을 구현 중입니다.

당신이 언급 한 table은 InnoDB 액세스 방법 (또는 Percona 또는 MariaDB에서 제공하는 다른 트랜잭션 친숙한 액세스 방법 중 하나)을 사용해야합니다.

테이블의 항목을 일괄 처리해야합니까? 즉, 그들은 어떻게 든 상호 연관되어 있습니까? 아니면 서버 프로세스가 하나씩 처리 할 수 ​​있습니까? 이것은 중요한 질문입니다. 개별적으로 또는 작은 배치로 처리 할 수 ​​있다면 서버 프로세스 간의로드 밸런싱을 향상시킬 수 있기 때문입니다. 작은 배치를 가정 해 봅시다.

아이디어는 다른 서버 프로세스에 해당 행이있는 경우 서버 프로세스가 테이블의 행을 점유하지 못하도록하는 것입니다. 나는 이런 종류의 일을 많이해야했고, 여기에 제 제안이 있습니다. 나는이 작품을 알아.

먼저 테이블에 정수 열을 추가하십시오. 그것을 "일하는"또는 그런 것으로 부르십시오. 기본값 인 0을 지정하십시오.

둘째, 각 서버에 영구 ID 번호를 할당하십시오. 서버의 IP 주소의 마지막 부분 (예 : 서버의 IP 주소가 10.1.0.123이고 ID 번호가 123 인 경우)은 사용 환경에 따라 고유하기 때문에 좋은 선택입니다.

그런 다음 서버가 작업 할 때이 두 가지 SQL 쿼리를 사용하십시오.

UPDATE table 
    SET working = :this_server_id 
    WHERE working = 0 
    AND time_scheduled < CURRENT_TIME 
    ORDER BY time_scheduled 
    LIMIT 1 

    SELECT table_id, whatever, whatever 
    FROM table 
    WHERE working = :this_server_id 

첫 번째 쿼리는 일관되게 일괄 처리 작업을 수행합니다. working = 0을 제외하고는 다른 서버 프로세스가 동시에 들어오는 경우 아무런 프로세스도 행을 가져올 수 없으므로 동일한 행을 가져 오지 않습니다. LIMIT 1은 배치 크기를 제한합니다. 당신은 이것을 할 필요는 없지만 그렇게 할 수는 있습니다. 나는 또한 가장 오래 기다렸던 행을 먼저 처리하기 위해 ORDER BY을 던졌다. 그것은 아마도 일을하는 데 유용한 방법 일 것입니다.

두 번째 쿼리는 작업을 수행하는 데 필요한 정보를 검색합니다. 작업중인 행에 대해 기본 키 값 (table_id)을 검색하는 것을 잊지 마십시오.

그런 다음 서버 프로세스는 필요한 모든 작업을 수행합니다.

완료되면 나중에 다시 대기열에 던져 넣어야합니다.이를 수행하려면 서버 프로세스가 time_scheduled을 필요에 맞게 설정 한 다음 working = 0으로 설정해야합니다. 예를 들어, 처리중인 각 행에 대해이 쿼리를 실행할 수 있습니다.

UPDATE table 
    SET time_scheduled = CURRENT_TIME + INTERVAL 5 MINUTE, 
     working = 0 
    WHERE table_id = ?table_id_from_previous_query 

그게 전부입니다.

한 가지를 제외하고. 현실 세계에서 이러한 큐잉 시스템은 때때로 파열됩니다. 서버 프로세스가 중단됩니다. 등. 머피의 법칙을 참고하십시오. 모니터링 쿼리가 필요합니다. 이 시스템에서 쉽습니다.

이 쿼리는 그 작업을해야하는데 서버와 함께, 5 분 이상 연체 모든 작업의 ​​목록을 제공합니다.

SELECT working, COUNT(*) stale_jobs 
    FROM table 
    WHERE time_scheduled < CURRENT_TIME - INTERVAL 5 MINUTE 
    GROUP BY WORKING 

이 쿼리가 비어 있으면 모두 정상입니다. working이 0으로 설정된 많은 작업이 발생하면 서버가 계속 작동하지 않습니다. 어떤 서버 ID 번호로 설정된 working의 작업이 발생하면 해당 서버는 점심 시간을 보냅니다. 필요가있을 경우

당신은이 쿼리와 함께 점심을 사라 서버에 할당 된 모든 작업을 재설정 할 수 있습니다.

UPDATE table 
    SET working=0 
    WHERE working=?server_id_at_lunch 

그런데 복합 지수가 (working, time_scheduled) 인 경우 실적이 좋을 것입니다.

+0

나는 그것이 잘 될 것이라고 생각한다. 아프다 그것을 구현하고 내가 예기치 않은 문제가 발생하는지보십시오. 고맙습니다! – fandangosoeren

+0

큰 운동을했습니다. 고마워, 또. – fandangosoeren

관련 문제