3

メソッドprocessReportは、同じ引数で並行して呼び出すことができます。processReportただし、2 つのプロセスが同じ $reportId で同時に呼び出した場合、処理は 1 回だけ実行する必要があります。この並行性の問題を解決するために、ヘルパー メソッドisLockedlockを作成しましたunlocklock$reportId の一時ファイルを作成します。isLocked一時ファイルが存在するかどうかを確認します。ファイルが存在する場合、処理は行われません。しかし、問題は、2 つの並列プロセスprocessReportが同じ $reportId で同時に呼び出されることです。この戦略が機能せず、処理が 2 回行われることがあります (これは明らかに、遅すぎるファイルシステムを使用しているために発生します)。プロセスはメモリを共有しないため、この並行性の問題を解決する方法がわかりません。同じ $reportId を 2 回処理しないようにする方法はありますか?

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);
}
4

2 に答える 2

2

ロックを「シミュレート」するいくつかの可能性を次に示します。

  1. flock - ファイルの排他ロックを取得できるため、他の PHP プロセスが待機します。
  2. Memcached::cas - memcache ベースのロック。cas ループを整理する必要があります。
  3. sem_acquire - 前述のように、セマフォ ベースのロック
  4. 共有メモリ- php には共有メモリ モジュールがあります
  5. 同じセッション ID - セッションごとに一度に 1 つのリクエストしか許可されないため、同じセッション ID を使用できます
于 2013-10-09T20:07:51.850 に答える