簡體   English   中英

如何防止Sidekiq對數據庫進行並行修改

[英]How to prevent Sidekiq from parallel modifications to database

我有一個工作人員試圖根據某些條件為照片找到匹配項。 每張照片都具有唯一的匹配項。 我編碼如下:

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

如您所見,worker獲取第一個通過條件的模型對象,然后更改match以將其從將來的worker匹配列表中排除。

問題是,當幾個工作人員一次執行任務時,他們都獲得相同的matches列表,因此修改了相同的實體。 但是我需要為每張照片進行唯一的匹配。

我該如何解決?

附加信息:

問:為什么要使用工人?

答:如果找不到匹配項,則需要稍后重試。

問:為什么要在多線程中使用Sidekiq?

答:我需要盡快處理照片。

大概我可以在每個人的開頭獲取當前在職工人的數量,並進行第n次比賽,而不是第一個。 但是該解決方案有點氣味,不是嗎?

更新:

附加問題:我可以在此問題上使用有關ActiveRecord鎖定的內容嗎? 我對with_lock和所有這些東西不是很熟悉。

解決您的問題的一個非常簡單的解決方案是分擔工作量,以免工人互相干擾。

如果您有2個工人,則可以給他們編號,然后對id photo.id % 2取模。 這樣,您只能得到0和1。 編號為0的工人只能按批處理,另一編號為1的工人。 通過增加模數,您可以增加所需數量的工人。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM