2012-05-30 2 views
2

두 개의 EC2 가용성 영역에 두 개의 redis 마스터 서버를 사용하여 작업 대기열을 작성하려고합니다. 모든 LPUSH 작업은 두 AZ의 두 마스터 시스템 모두에 대해 응용 프로그램 계층에서 수행됩니다. 이상적으로는 GitHub's resque을 사용하지만 여러 AZ에서 복수 마스터의 does not seem to have any notion을 리졸브하는 것이 이상적입니다.여러 redis 마스터 서버에서 큐 구현

한 작업자 만 특정 작업을하고 있는지 확인해야합니다. 일부 근로자는 1A 1A에서 redis 기계와 1A로 통화하고 일부는 AZ 1B에서 1B로 통화 할 것입니다. 나는 1A의 작업자와 1B의 작업자가 서로 다른 redis 마스터로부터 동일한 작업을 제거하고 동시에 작업을 시도하는 시나리오를 피할 필요가 있습니다.

이 작업자 의사 코드에 내가 놓친 경쟁 조건이 있습니까? 당신이 본질적으로 무엇을하려고

job_id = master1.BRPOPLPUSH "queue", "working" 
m1lock = master1.SETNX "lock.#{job_id}" 
m2lock = master2.SETNX "lock.#{job_id}" 
completed = master1.ZSCORE "completed", job_id 

if completed 
    # must have been completed just now on other server, no-op 
    master1.LREM "working", 0, job_id 
    master1.del "lock.#{job_id}" 
    master2.del "lock.#{job_id}" 
elsif not m1lock or not m2lock 
    # other server is working on it? We will put back at the end of our queue 
    master1.LPUSH "queue", job_id 
    master1.LREM "working", 0, job_id 
    master1.del "lock.#{job_id}" if m1lock 
    master2.del "lock.#{job_id}" if m2lock 
else 
    # have a lock, it's not complete, so do work 
    do_work(job_id) 

    now = Time.now.to_i 
    master1.ZADD "completed", now, job_id 
    master2.ZADD "completed", now, job_id 

    master1.del "lock.#{job_id}" 
    master2.del "lock.#{job_id}" 

    master1.LREM "working", 0, job_id 
    master2.LREM "queue", 0, job_id # not strictly necessary b/c of "completed" 
end 

답변

1

는 큐 또는 다른 아무것도, 레디 스를 지원하지 않습니다, 그리고 당신의 의사 코드는 경쟁 조건이 있는지, 마스터 - 마스터 복제입니다. 단지 일 :

m1lock = master1.SETNX "lock.#{job_id}" 
m2lock = master2.SETNX "lock.#{job_id}" 

당신이이 일을하는 동안 다른 작업자가 작업을 할 수 있으며,이 명 노동자에서 한 번에 작업을 의미합니다.redis가 패턴에 이상적이라고 생각하지 않습니다. 그런 식으로 작동 할 수있는 대기열 서버를 알지 못하지만 다시 그런 서버를 많이 모릅니다. 따라서 확신 할 수 있습니다.

하나의 마스터 만 작업을 한 번에 가져올 수 있도록 작업의로드를 조정하면 가능하지만 그 중 하나가 아닌 두 개의 큐가 본질적으로 있습니다.

+0

SETNX는 잠금을 확보 할 수없는 경우 실패를 반환하므로 이론적으로 동시에 실행하고 작업을 수행하지 않으면 둘 다 실패하게됩니다. 그래서 나는 괜찮을 것이라고 생각합니다 (한 경우에 대기열에서 단지 1 번만 반복적으로 잠글 수없는 상황에서 끝낼 수 있기 때문에 일종의 백 오프 기간을 원할 수 있습니다. 그러나 현실 세계에서 대기열의 길이는 가변적이므로 머물러 있을지는 의문입니다. 매우 긴 경우). 나는 redis가 이것을 지원하지 않는다는 것을 알기 때문에 EC2 머신과 AZ는 실패 할 수 있기 때문에 어플리케이션 레벨에서 그것을 할 필요가 있습니다. ... – esilver

+0

클라이언트가 가장 먼저 마스터가 아닌 가장 먼저 마스터를 처리하는 경우 그것은 연쇄 복제 (마스터 - 슬레이브/마스터 - 슬레이브)와 정말로 다른가요? –

+0

내 실제 코드에서 클라이언트는 가장 가까운 마스터 (자신의 AZ에있는 마스터)에게 연락을 시도하고, 그렇지 않으면 다른 AZ의 마스터에 갈 것입니다. (2011 년 4 월 Amazon Cloudpocalypse에서 FWIW를 사용하면 두 개의 AZ 중 하나에서 마스터 시스템을 완전히 종료해야했기 때문에이 방법을 사용할 수 있습니다 ...) – esilver

0

AWS 환경에 이미 있다면 아마존의 SQS 서비스를 사용하지 않는 이유는 무엇입니까? 나는 과거와 함께 일해 왔으며 엉덩이에 약간의 고통이 있음을 깨달았지만 아마존에서 가장 성숙한 서비스이며이 시나리오를 위해 만들어진 목적입니다.

+0

블로그 게시물 : https://github.com/blog/542-introducing-resque Quote : "우리는 젊은 사이트 였고 푸시와 팝 사이의 여러 분 지연 시간에 관한 Amazon 포럼에 대한 이야기를 들었습니다. 즉, 한 번 당신은 대기열에 뭔가를 집어 넣으면 당분간은 되돌릴 수 없을 것입니다. 그래서 겁이 나서 우리가 이사했습니다. " 또한 많은 대기열 작업을 수행하여 비용이 많이들 것이라고 염려합니다. 기본적으로 모든 쓰기 작업을 예측할 수없는 쓰기 대기 시간 때문에 RDS에 큐에 넣으려고합니다. – esilver

+0

LMAO ... 좋은 전화입니다. RDS 대기 시간에 나를 시작하지 마십시오.나는 그 불에 타 없어졌다. 참고로, RDS 대기 시간이 오래 걸리면 오래된 학교 (실제 하드웨어라고도 함)를 실행하는 mysql이 하루 종일 RDS에서 쫓겨납니다. RDS 대기 시간 문제에 직면했을 때 우리는 mysql 데이터베이스를 클라우드에서 끌어 와서 시스템을 카산드라와 redis로 전환 한 후에 만 ​​클라우드로 되돌아갔습니다. – codemonkey

+0

우리의 경험은 RDS 대기 시간이 그렇지 않을 때를 제외하고는 매우 훌륭하다는 것입니다 (매우 매우 낮음을 의미). 사실 좀 더 조사한 후에 Amazon SQS 솔루션으로 이동하고 SQS를 통해 RDS에 100 % 기록합니다. 무언가를 SQS 대기열에서 꺼내려면 몇 분이 걸릴지라도, 우리의 작업 부하는 견딜 수 있습니다. – esilver