如何在php中管理并发问题?

时间:2013-10-09 17:44:26

标签: php multiprocessing

可以使用相同的参数并行调用方法processReport。但是,如果两个进程同时使用相同的$ reportId调用processReport,则应该只进行一次处理。为了解决这个并发问题,我创建了辅助方法isLockedlockunlocklock为$ reportId创建临时文件。 isLocked检查临时文件是否存在。如果文件存在则不应该进行处理。但问题是两个并行进程同时使用相同的$ reportId调用processReport有时这个策略不起作用并且处理完成两次(这显然是因为使用文件系统太慢而发生)。由于进程不共享内存,我不知道如何解决这个并发问题。有没有办法避免两次处理相同的$ reportId?

private function getLockFileName($reportId) {
    return sprintf('%s/%s.lock', sys_get_temp_dir(), $reportId);
}

private function isLocked($reportId) {
    return file_exists($this->getLockFileName($reportId));
}

private function lock($reportId) {
    touch($this->getLockFileName($reportId));
}

private function unlock($reportId) {
    unlink($this->getLockFileName($reportId));
}

public function processReport($reportId) {
    if ($this->isLocked($reportId)) return;

    $this->lock($reportId);

    // processing should be done only once for the same $reportId

    $this->unlock($reportId);
}

2 个答案:

答案 0 :(得分:2)

以下是“模拟”锁定的几种可能性

  1. flock - 您可以获取文件的独占锁定,因此其他php进程将等待
  2. Memcached::cas - 基于memcache的锁,你需要组织cas loop
  3. sem_acquire - 如上所述,基于信号量的锁
  4. Shared Memory - php共享内存模块
  5. Same session id - 您可以使用相同的会话ID,因为每次会话一次只允许一个请求

答案 1 :(得分:1)

semaphore extension是为这种情况而建的。例如:

public function processReport($reportId) {
    $sem = sem_get("report-$reportId");

    sem_aquire($sem);  // Wait until the semaphore is free

    // processing should be done only once for the same $reportId

    sem_remove($sem);  // Release for another request
}

您还可以使用APC或memcached将自己的快速锁写入共享内存。或者甚至更好地在第一次运行时将报告的结果写入共享内存,以便将来的请求更快地获得它。