我有在多種類型的資源上處理的sidekiq作業。但是,對於特定類型的資源,例如:資源X,我需要確保在任何給定時間只有一個sidekiq作業可以處理該特定資源。例如,如果我有3個sidekiq作業同時排隊,並且想要與資源X進行交互,那麼只有一個sidekiq作業可以處理資源X,而其餘的兩個作業將不得不等待(或重新排隊) ),直到當前正在處理資源的sidekiq作業完成。當現有的sidekiq作業正在處理特定的資源時,阻止/重新排隊處理其他sidekiq作業
當前,我試圖在數據庫表中添加一條記錄,以便在sidekiq作業正在處理資源時使用該記錄來阻止其他sidekiq作業處理資源,直到該記錄被sidekiq作業從數據庫中刪除(當它完成處理資源X時)或經過一段時間後(例如:如果記錄創建超過5分鐘前,則認爲它不再擁有對資源X的獨佔訪問權,並且下一個sidekiq想要處理資源X的作業可能會改變該記錄並要求獨佔訪問資源X)。
我當前實現的僞代碼:
def perform(res_id, res_type)
# Only applies to "RESOURCE_X"
if res_type == RESOURCE_X
if ResourceProcessor.where(res_id).empty? || ((Time.now-ResourceProcessor.where(res_id).first.created_at) > 5.minutes)
ResourceProcessor.create(res_id: res_id).save
process_resource_x(res_id)
else
SidekiqWorker.delayed(res_id, res_type, 5.minutes) #Try again later
return
end
#Letting other sidekiq jobs know they can now fight over who gets to process resource X
ResourceProcessor.where(res_id).destroy
else
process_other_resource(res_id)
end
end
不幸的是,我的解決辦法是行不通的。如果希望處理資源X的sidekiq作業之間存在延遲,則工作得很好。但是,如果要處理資源X的作業同時到達,那麼我的解決方案就會崩潰。
有沒有什麼辦法可以在處理資源X時執行某種同步?
順便說一句,我的sidekiq作業可能分佈在多臺機器上(但他們訪問專用機器上的同一個redis服務器)。
您可能正在尋找一個**鎖**,以便一次只有一個線程/進程修改資源。這裏有一個很好的閱讀,建議使用數據庫來協調鎖定:https://makandracards.com/makandra/31937-differences-between-transactions-and-locking。在[with_advisory_lock gem](https://github.com/mceachen/with_advisory_lock)中實現了一些更多的鎖定策略。 –