lockPath($ticketId); if ($this->isStaleLock($path)) { @unlink($path); } if (is_file($path)) { return false; } $payload = json_encode([ 'ticket_id' => $ticketId, 'pid' => getmypid(), 'time' => time(), ], JSON_UNESCAPED_UNICODE); $written = @file_put_contents($path, $payload, LOCK_EX); return $written !== false; } /** * 释放锁 */ public function release(int $ticketId): void { $path = $this->lockPath($ticketId); if (is_file($path)) { @unlink($path); } } private function lockPath(int $ticketId): string { $runtime = defined('RUNTIME_PATH') ? RUNTIME_PATH : (dirname(__DIR__, 3) . '/runtime/'); $dir = $runtime . 'split_ticket_sync/'; if (!is_dir($dir)) { @mkdir($dir, 0755, true); } return $dir . $ticketId . '.lock'; } private function isStaleLock(string $path): bool { if (!is_file($path)) { return false; } $mtime = (int) @filemtime($path); return $mtime > 0 && (time() - $mtime) > self::LOCK_TTL; } }