2014-02-05 2 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) 

Логика: Если это первый раз в течение дня, новый регистр создается, если нет, то просто действие увеличивается в этот день.

Иногда я вижу в db, что приложение было сохранено дважды, потому что у меня много очереди в очереди, и у меня работает 10 человек.

Может ли кто-нибудь помочь мне избежать этого?

PS: Извините за мой английский.

+0

Какую версию рельсов вы используете? – BroiSatse

ответ

1

Причина это происходит нить параллелизм:

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) 

Чтобы избежать этого, необходимо использовать ActiveRecord операции:

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 

ActiveRecord сделок не атомное, поэтому ни один поток будет перепрыгивать между этими двумя утверждениями ,

+1

Но не могли ли два потока иметь несохраненный новый объект StatsApp? Если «новое» не изменено на «создание», я думаю, что все еще будет проблема? – SteveTurczyn

+0

Вы правы, должны быть созданы, а не инициализированы. Ответ обновлен. – BroiSatse

+0

Привет, ребята! Это звучит неплохо, но у меня есть ошибка, когда я пытаюсь сделать stat.increment (action). 'Ошибка: неправильное количество аргументов (1 для 3) /home/app/models/stats_app.rb:10:in increment ' Любые идеи, почему? – 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 

Спасибо, ребята!

Смежные вопросы