10

嘿。我使用delayed_job 进行后台处理。我有 8 个 CPU 服务器,MySQL,我启动了 7 个延迟作业进程

RAILS_ENV=production script/delayed_job -n 7 start 

Q1: 我想知道是否有可能 2 个或更多延迟作业进程开始处理同一个进程(数据库延迟作业中的同一记录行)。我检查了delayed_job 插件的代码,但找不到应有的锁定指令(没有锁定表或SELECT...FOR UPDATE)。

我认为每个进程都应该在 lock_by 列上执行 UPDATE 之前锁定数据库表。他们只需通过更新locked_by 字段来锁定记录(UPDATE delayed_jobs SET locked_by...)。真的够了吗?不需要锁吗?为什么?我知道 UPDATE 比 SELECT 具有更高的优先级,但我认为这在这种情况下没有效果。

我对多线程情况的理解是:

Process1: Get waiting job X. [OK]
Process2: Get waiting jobs X. [OK]
Process1: Update locked_by field. [OK]
Process2: Update locked_by field. [OK]
Process1: Get waiting job X. [Already processed]
Process2: Get waiting jobs X. [Already processed]

我认为在某些情况下,更多的工作可以获得相同的信息并可以开始处理相同的流程。

Q2: 对于 8CPU 的服务器来说,7 个延迟作业是一个好的数字吗?为什么是/不是。

谢谢 10 倍!

4

1 回答 1

11

我认为您的问题的答案在“lib/delayed_job/job.rb”的第 168 行:

self.class.update_all(["locked_at = ?, locked_by = ?", now, worker], ["id = ? and (locked_at is null or locked_at < ?)", id, (now - max_run_time.to_i)])

此处仅在没有其他工作人员已锁定作业的情况下才执行行的更新,并且检查表是否已更新。不需要表锁或类似的东西(顺便说一句,这会大大降低您的应用程序的性能),因为您的 DBMS 确保单个查询的执行与其他查询的影响隔离。在您的示例中,Process2 无法获得作业 X 的锁定,因为当且仅当它之前未锁定时,它才会更新作业表。

对于你的第二个问题:这取决于。在 8 CPU 服务器上。这是专门用于这项工作的,8 个工作人员是一个很好的起点,因为工作人员是单线程的,你应该为每个核心运行一个。根据您的设置,或多或少的工人会更好。这在很大程度上取决于你的工作。利用多核优势您的工作?还是您的工作大部分时间都在等待外部资源?您尝试了不同的设置并查看了所有相关资源。

于 2010-04-25T12:03:10.597 回答