У меня есть веб-сайт, на котором в одно и то же время несколько пользователей могут одновременно писать в один и тот же файл. Пример моего кода ниже.

PHP 5.6.20

<?php
$root=realpath($_SERVER["DOCUMENT_ROOT"]);
$var=time()."|";
echo $var."<br/>";
$filename=$root."/Testing/Testing/test1.txt";

$myfile=fopen($filename,"a");
fwrite($myfile,$var);
fclose($myfile);

$myfile=fopen($filename,"r");
$contents = fread($myfile, filesize($filename));
echo $contents;
fclose($myfile);
?>

Я читал, что в PHP, если несколько пользователей пытаются записать в один и тот же файл один и тот же файл, существует вероятность повреждения данных, я, конечно, не хочу иметь код, который может вызвать некоторое повреждение данных в долгосрочной перспективе ,

Я попытался запустить приведенный выше код практически в одно и то же время в своем браузере, чтобы симулировать одновременную запись нескольких пользователей в один и тот же файл, и это не привело к ошибкам или повреждению данных в файле, в который выполняется запись, но я все еще не уверен в будущих повреждениях данных.

Я прочитал, что могу использовать flock, чтобы убедиться, что 2 пользователя не могут одновременно писать в файл, но так как я протестировал приведенный выше код и он не вызвал повреждения данных, я не уверен, стоит ли обновлять мой код с помощью собираться или просто оставить все как есть.

Мои вопросы:

1) Есть ли вероятность того, что приведенный выше код повредит файл, в который он записывает?

2) если да, то использует ли flock эту проблему? если да, то как мне реализовать flock в приведенном выше коде?

< Сильный > Edit:

Я знаю, что эту неопределенность можно решить с помощью базы данных, но для этого случая лучше использовать простой текст, поэтому, пожалуйста, не предлагайте мне использовать БД.

Заранее спасибо.

3
John Colbir 2 Сен 2017 в 21:09

4 ответа

Лучший ответ

Это общая теоретическая проблема для многих веб-приложений на многих языках программирования.

Ответ - да, это МОЖЕТ вызвать проблемы. Однако это очень теоретическая проблема, если содержимое, которое вы добавляете в файлы, не очень велико и у вас нет большого трафика. Современные операционные системы и файловые системы настолько хорошо оптимизированы (кэширование, ленивая запись и т. Д.), Что это вряд ли произойдет, когда вы закроете свои файловые дескрипторы сразу после их использования.

Вы можете добавить что-то вроде буфера, если вы столкнетесь с ошибкой (проверьте права доступа перед тем, как писать с PHP / перехватывать исключения на других языках) и попробуйте снова через некоторое время или запишите свой буфер во временный файл и объедините его с другим процессом - у вас есть несколько возможностей.

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

1
iquellis 2 Сен 2017 в 18:30

Я не знаком с паствой, но моя первая мысль - механизм блокировки или организации очередей. Если записанные данные не нужно использовать или просматривать для пользователей, тогда лучшим выбором будет рабочая очередь. Записать данные в систему на основе Redis или Memcached, SQL или другого типа системы очередей, или просто сбросить уникальные метки времени с интересным содержимым в каталог, который работник может собирать в порядке возрастания в файл MASTE.

Для случаев использования, когда записанные данные инициируют что-то, что необходимо пользователю для получения отчета или результата, ответа или другой обратной связи, блокировка может быть способом, если вы не можете перепроектировать асинхронный стек с возможной согласованностью. Это также сложно узнать, не зная нагрузки и количества одновременно работающих пользователей, количества серверов и т. Д.

1
Canis 2 Сен 2017 в 18:28

Если два сценария пытаются выполнить запись в файл одновременно. Функция fopen (), когда вызывается для файла, не препятствует открытию того же файла другим скриптом, что означает, что вы можете найти один скрипт, читающий из файла, когда другой пишет, или, что еще хуже, два скрипта, записывающие в один и тот же файл одновременно. Так что хорошо использовать flock (). Вы можете получить дополнительную помощь на http: //www.hackingwithphp. com / 8/11/0 / lock-files-with-flock. Для вашего кода вы можете использовать flock () как

<?php
$root=realpath($_SERVER["DOCUMENT_ROOT"]);
$var=time()."|";
echo $var."<br/>";
$filename=$root."/Testing/Testing/test1.txt";

$myfile=fopen($filename,"a");
if (flock($myfile, LOCK_EX)) {        
    fwrite($myfile,$var);
    flock($myfile, LOCK_UN); // unlock the file
} else {
    // flock() returned false, no lock obtained
    print "Could not lock $filename!\n";
}

fclose($myfile);

$myfile=fopen($filename,"r");
if (flock($myfile, LOCK_EX)) {        

    $contents = fread($myfile, filesize($filename));
    echo $contents;
    flock($myfile, LOCK_UN); // unlock the file
} else {
    // flock() returned false, no lock obtained
    print "Could not lock $filename!\n";
}
fclose($myfile);
?>
1
Tim Krief 5 Май 2020 в 08:14

Вам нужно изменить механизм сохранения из простого файла в любую базу данных с транзакциями.

-1
Artur Poniedziałek 2 Сен 2017 в 18:15