일부 조건에 따라 사진의 일치 항목을 찾는 작업자가 있습니다. 각 사진은 고유 한 성냥을가집니다.Sidekiq가 데이터베이스를 병렬로 수정하지 못하도록하는 방법
class PhotoDeliveryWorker
include Sidekiq::Worker
def perform(photo_id)
photo = Photo.find(photo_id)
unless photo.match
matches = Photo.where(some_condition: "some_value")
match = matches.first
if match
# Do something to photo
photo.match = match
if photo.save
match.some_condition = "another_value"
else
schedule photo_id
end
else
# Couldn't find a match
schedule photo_id
end
end
end
private
def schedule(photo_id)
PhotoDeliveryWorker.perform_in 1.hours, photo_id
end
end
당신이 볼 수 있듯이, 작업자가 조건을 통과 한 후 향후 근로자에서 제외하는 match
을 변경 목록과 일치하는 첫 번째 모델 객체를 가져옵니다 I는 다음과 같이 코딩.
문제는 한 번에 여러 명의 작업자가 수행 할 때 모두 동일한 matches
목록을 얻고 결과적으로 동일한 엔티티를 수정하는 것입니다. 하지만 각 사진마다 고유 한 일치가 필요합니다.
어떻게 해결할 수 있습니까?
추가 정보 :
Q : 왜 근로자를 이용합니까?
A : 일치하는 항목을 찾을 수없는 경우 나중에 다시 시도해야합니다.
Q : Sidekiq를 여러 스레드와 함께 사용하는 이유는 무엇입니까?
A : 최대한 빨리 사진을 처리해야합니다.
아마 각각의 시작 부분에 현재 활동중인 직원의 수를 얻고 첫 번째가 아닌 n 번째 일치를 얻을 수 있습니다. 하지만 그 해결책은 약간의 냄새가 난다.
UPDATE :
추가 질문 : 액티브가이 문제를 잠금에 대해 뭔가를 사용할 수 있을까요? 나는 with_lock
과이 모든 것들에 익숙하지 않다.
이렇게하기 위해 원시 SQL로 드롭 다운 할 수 있습니다 :'UPDATE photos SET match_id =? 여기서 id =? match_id는 NULL이다. 이렇게하면 첫 번째 업데이트 만 레코드를 찾아 업데이트합니다. –
간단한 조건으로 가정하면, 사진 ID로 조건 당 redis list/set를 유지하고 'BRPOP'또는 'RPOP'를 사용하여 일치하는 ID를 가져오고이 ID가 결코 재사용되지 않도록 할 수 있습니다. 편집 : 아마 모든 ID가있는 목록/세트를 처리하여 재발행되지 않도록 할 수 있습니다. – lwe