Rails,Heroku和Resque:长时间运行的背景作业优化

我们正在构建一个火种风格的应用程序,允许用户“喜欢”或“不喜欢”事件。 每个活动都有大约100个与之关联的关键字。 当用户“喜欢”或“不喜欢”和事件时,我们将该事件的关键字与用户相关联。 用户可以快速获得数千个关键字。

我们使用表格将用户和事件与关键字(event_keywords和user_keywords)相关联。 直通表有一个额外的列relevant_score,它是一个浮点数(例如,如果关键字非常relevance_score ,则关键字可以是0.1,如果它非常相关则可以是0.9)。

我们的目标是根据用户的关键字向用户展示最相关的活动。 所以Events有许多属于用户的event_rankings。 从理论上讲,我们希望为每个用户对所有事件进行不同的排名。

以下是模型:

User.rb:

  has_many :user_keywords, :dependent => :destroy has_many :keywords, :through => :user_keywords has_many :event_rankings, :dependent => :destroy has_many :events, :through => :event_rankings 

Event.rb

  has_many :event_keywords, :dependent => :destroy has_many :keywords, :through => :event_keywords has_many :event_rankings, :dependent => :destroy has_many :users, :through => :event_rankings 

UserKeyword.rb:

  belongs_to :user belongs_to :keyword 

EventKeyword.rb:

  belongs_to :keyword belongs_to :event 

EventRanking.rb:

  belongs_to :user belongs_to :event 

Keyword.rb:

  has_many :event_keywords, :dependent => :destroy has_many :events, :through => :event_keywords has_many :user_keywords, :dependent => :destroy has_many :users, :through => :user_keywords 

我们有一种方法可根据关键字计算事件与特定用户的相关程度。 这种方法运行得非常快,因为它只是数学。

User.rb:

 def calculate_event_relevance(event_id) ## Step 1: Find which of the event keywords the user has ## Step 2: Compare those keywords and do math to calculate a score ## Step 3: Update the event_ranking for this user end 

每当用户“喜欢”或“不喜欢”某个事件时,就会创建一个后台作业:

RecalculateRelevantEvents.rb:

 def self.perform(event_id) ## Step 1: Find any events that that share keywords with Event.find(event_id) ## Step 2: calculate_event_relevance(event) for each event from above step end 

所以这里是这个过程的总结:

  1. 用户喜欢或不喜欢活动
  2. 创建后台作业,其在步骤1中查找与事件类似的事件
  3. 根据用户的关键字重新计算每个类似事件

我正试图找出优化我的方法的方法,因为它很快就会失控。 普通用户将每分钟刷过大约20个事件。 一个事件最多可以有1000个类似的事件。 每个活动大约有100个关键字。

因此,根据我的方法,每次滑动,我需要遍历1000个事件,然后在每个事件中循环100个关键字。 每个用户每分钟发生20次。

我该怎么办呢?

你需要按滑动计算吗? 你可以debounce它,并且每5分钟为用户重新计算一次吗?

这个数据不需要每秒更新20次才有用,事实上,每秒更新一次可能更有用。

通过5分钟的去抖动,您可以从每位用户的6,000(20 * 60 * 5)次重新计算到同期的1次 – 相当大的节省。

如果可以的话,我还建议使用sidekiq,通过multithreading处理,你可以大大增加同时工作的数量 – 我是一个很大的粉丝。

一旦你使用它,你可以尝试一下这样的gem: https : //github.com/hummingbird-me/sidekiq-debounce

……这提供了我所暗示的那种去抖动。