2014-02-05 3 views
0

여기 있습니다! Ruby on Rails로 플랫폼을 구축하고 있습니다. 일부 통계를 저장하기 위해 Resque - Redis를 사용하고 있으며 몇 가지 문제점을 발견했습니다.데이터가 두 번 저장됩니다 - Resque

앱이 하루에 여러 번 작업을 저장해야합니다. 예를 들어 앱을 실행 한 경우이 앱이 해당 날짜에 실행되었음을 저장해야합니다. 문제는 앱을 여러 사용자가 동시에 사용할 수 있으며 문제가 발생한다는 것입니다.

unless stat = self.where(app_id: app_id, day: fire_at.to_date).first 
    stat = StatsApp.new(app_id: app_id, day: fire_at.to_date) 
end 

stat.increment(action) 

논리 : 하루 중 처음으로 새 레지스터가 만들어지면 새 레지스터가 만들어지고, 그렇지 않은 경우 현재 동작이 증가됩니다.

때때로 대기열에 많은 프로세스가 있고 10 명의 작업자가 실행 중이기 때문에 응용 프로그램이 두 번 저장되었다는 것을 db로 볼 수 있습니다.

아무도 나를 피할 수 있었습니까?

추신 : 내 영어로 죄송합니다.

Thread 1: stat = self.where(app_id: app_id, day: fire_at.to_date).first #=> false 
Thread 2: stat = self.where(app_id: app_id, day: fire_at.to_date).first #=> false 
Thread 2: stat = StatsApp.new(app_id: app_id, day: fire_at.to_date) 
Thread 1: stat = StatsApp.new(app_id: app_id, day: fire_at.to_date) 

는 액티브 트랜잭션을 사용하기 위해 필요한이를 방지하려면 :

+0

사용중인 레일 버전은 무엇입니까? – BroiSatse

답변

1

이런 일이 발생하는 이유는 스레드 동시성

stat = self.transaction do 
    self.where(app_id: app_id, day: fire_at.to_date).first || StatsApp.create(app_id: app_id, day: fire_at.to_date) 
end 
, 그래서 스레드가 두 문 사이에 원자 이동하지 않습니다되어

액티브 거래 .

+1

그러나 두 개의 스레드 모두 저장되지 않은 새로운 StatsApp 개체를 가질 수 있습니까? "new"가 "create"로 변경되지 않으면 문제가 여전히 남아 있다고 생각합니까? – SteveTurczyn

+0

맞습니다. 초기화되지 않아야합니다. 답변이 업데이트되었습니다. – BroiSatse

+0

안녕 얘들 아! 그게 좋겠지 만, stat.increment (action)을 시도 할 때 오류가 있습니다. '오류 : 잘못된 인수 수 (1에 대해 3) /home/app/models/stats_app.rb:10:in 증가분 ' 이유가 무엇입니까? – Luismiv85

0

글쎄, 몇 시간 후에 해결책을 찾았습니다!

StatsApp.transaction do 

    stat = self.where(app_id: app_id, day: fire_at.to_date).lock(true).first || StatsApp.create(app_id: app_id, day: fire_at.to_date) 

    stat.increment(action) 
    stat.save 

end 

감사합니다 !!

관련 문제