【问题标题】:Task Queue in PHP / MySQL: Race ConditionPHP / MySQL 中的任务队列:竞争条件
【发布时间】:2013-01-14 10:38:19
【问题描述】:

我正在 PHP 中实现一个离线任务队列。在线页面在此表中插入一条记录以安排工作:

create table sl_task_queue (
    task_id int primary key auto_increment,
    task_data varchar(255) not null,
    started_date datetime,
    completed_date datetime,
    priority int not null default 10
) ENGINE=Innodb;

然后,在离线状态下,我有一个 PHP CLI 进程池,它们处于循环中等待工作完成。为了查询工作,他们运行这个函数:

$SEMKey = "849039";
$seg = sem_get( $SEMKey, 2, 0666, -1) ; 

function getTask() {
    sem_acquire($GLOBALS['seg']);

    // This function returns null for no results, or a Task ORM object on success
    $Task = eSqlObject("Task", "select * from sl_task_queue 
        where started_date is null 
        order by task_id asc limit 1 for update"); 

    if( $Task ) {
        // Set started_date to claim this task
        $Task = new LucidityTask($hash);
        $Task['started_date'] = date("Ymd H:i:s");
        $Task->save(); // performs an UPDATE query
    }

    sem_release($GLOBALS['seg']);   

    return $Task;
}

我在这里尝试了两件事,一个 PHP 信号量和 MySQL 的“SELECT ... FOR UPDATE”功能。我还尝试了一个完整的 LOCK TABLE 命令。尽管如此,我仍然在守护进程中的两个进程声称同一行时遇到问题,我无法确定原因。几个怀疑 - 当您执行单独的 CLI 进程时,PHP 的信号量是否进入 derp 模式?或者 MySQL 是否在花时间实际更新基础表数据,以便在此函数退出后,SELECT 查询仍会在短时间内返回旧数据?

还有其他想法吗?

非常感谢!

【问题讨论】:

  • 但是您打算一次最多执行 2 个进程?
  • 池大小取决于要完成的工作量。我现在将它设置为一次最多 40 个进程,所以这需要很好地处理并发。
  • 现在可以使用了吗?很高兴我能指出正确的方向。
  • 嘿,你的评论触发了灯泡。非常感谢!

标签: php mysql queue conditional-statements race-condition


【解决方案1】:

啊!这就是为什么复制/粘贴是邪恶的。问题来了:

$seg = sem_get( $SEMKey, 2, 0666, -1) ; 

“2”允许两个进程同时获取信号量。谢谢,路易斯 H.!

【讨论】:

    【解决方案2】:

    添加附加字段...例如 uniqueID

    1) 生成唯一ID ...

    $uniqueID = uniqid();
    

    2) 更新一行。设置字段 uniqueID = $uniqueID

    3) 选择 1 行,其中 uniqueID = $uniqueID 如果行存在 -> 做其他工作 -> 尝试标记/获取另一条记录

    4) 作业完成后删除 uniqueID = $uniqueID 的行。

    利润! :)

    此外,您可以设置“endTime” = currentDateTime + N_Minutes(分钟 - 该行将被锁定多长时间) 并在 endTime 时清除 uniqueID

    【讨论】:

      猜你喜欢
      • 2019-07-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-13
      • 1970-01-01
      • 2010-10-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多