[英]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.