PHP 5.x синхронизированный доступ к файлам (без базы данных) - PullRequest
6 голосов
/ 09 октября 2008

Я в основном знаком с Java, C и C ++, в которых есть способы контролировать, что только один поток обращается к ресурсу в любой момент времени. Сейчас я ищу что-то похожее, но в PHP 5.x.

Чтобы сформулировать мою проблему на одном примере:

У меня есть ASCII-файл, в котором хранится только число, значение счетчика загрузки страницы. При развертывании приложения файл будет просто содержать 0. Для каждого доступа значение будет увеличиваться на единицу. Цель состоит в том, чтобы отслеживать загрузку страниц.

Проблема возникает, когда многие пользователи одновременно получают доступ к странице, содержащей счетчик. Когда поток A прочитал текущее значение, скажем, 11, другой поток, который мы называем B, читает значение, все еще 11. Затем первый поток A увеличивает значение чтения и записывает 12 в файл и закрывает его. Затем второй поток B увеличивает значение чтения, равное 11, получает 12 и записывает это в файл. Значение 12 сохраняется в файле, когда оно действительно должно быть 13.

На другом языке программирования я бы решил это, используя мьютекс. Я понимаю, что в состав модулей входят мьютексы, разделяемая память и другая функциональность. Но я хотел бы получить решение, которое работает на «большинстве серверов». Независимая платформа. Устанавливается на самых дешевых веб-хостах. Есть ли хорошее решение этой проблемы? И если нет, то какой путь вы бы выбрали, если использование базы данных не вариант ?

Ответы [ 2 ]

7 голосов
/ 09 октября 2008

Вы можете попробовать php-вариант стада (http://www.php.net/flock)

Я бы предположил нечто подобное (предполагается, что файл /tmp/counter.txt уже существует и в нем есть счетчик):

<?php

$fp = fopen("/tmp/counter.txt", "r+");

echo "Attempt to lock\n";
if (flock($fp, LOCK_EX)) {
  echo "Locked\n";
  // Read current value of the counter and increment
  $cntr = fread($fp, 80);
  $cntr = intval($cntr) + 1;

  // Pause to prove that race condition doesn't exist
  sleep(5);

  // Write new value to the file
  ftruncate($fp, 0);
  fseek($fp, 0, SEEK_SET);
  fwrite($fp, $cntr);
  flock($fp, LOCK_UN); // release the lock
  fclose($fp);
}

?>
3 голосов
/ 09 октября 2008

PHP-функция flock () - это путь. Однако вы должны убедиться, что все доступы к файлу защищены в первую очередь вызовом flock (). PHP не будет проверять, заблокирован ли файл, если вы не сделаете этого явно.

Концепция практически идентична мьютексам (защита общих ресурсов и т. Д.), Но она достаточно важна, чтобы иметь особый акцент.

...