Какую нагрузку держит чтение/запись файлов в PHP?

123 4
BrokenBrake
На сайте с 03.03.2007
Offline
194
2716

Столкнулся с неприятной проблемой.

На одном из серверов происходит что-то странное.

Объясняю. Откручивается рекламная строчка. Количество показов записывается в файле var/stat.php, который формируется простейшим var_export из массива.

Количество просмотров не слишком и большое, но приличное: около 100 тыс. в сутки.

Так вот, периодически из файла пропадает ЧАСТЬ массива 8-/

Кто сталкивался с подобным поведением и куда копать?

edogs software
На сайте с 15.12.2005
Offline
775
#1

копать тут -> http://ru.php.net/flock , применяйте вдумчиво, иначе будет только хуже:)

p.s.: "нагрузка на чтение/запись файлов" в php абсолютно не при чем. это стандартное поведение файлов, когда с ними работают без блокировки. файл-то один, а конкурентов пытающихся в него инфу скинуть куча. если Вы не управляете очередностью записи, то получаете то, что получаете.

BrokenBrake:
edogs, разве информация при file_put_contents не целиком пишется?

Это не блокирущая запись.

BrokenBrake:
Я не вполне понимаю... то есть вы хотите сказать, что может быть ситуация, когда в момент записи файла (то есть она ещё не вполне завершилась), файл может прочитаться другим скриптом, пока он ещё не полностью сформирован?

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

Блокировка файлов единственный способ это контроллировать. И это относится не только к php, а в принципе к работе с файлами. Плюс обязательно прочтите про особенности flock в мануале php, там есть неочевидные вещи типа "all accessing programs have to use the same way of locking or it will not work" и "On some operating systems flock() is implemented at the process level. When using a multithreaded server API like ISAPI you may not be able to rely on flock() to protect files against other PHP scripts running in parallel threads of the same server instance!" и пара других.

BrokenBrake:
Значит ли это, что для использования блокировки придётся отказываться от удобнейших file_get_contents и file_put_contents? В мануале сказано:

Да, прийдется! Даже более того, в мануале сказано "all accessing programs have to use the same way of locking or it will not work". То есть все другие способы не использующие flock обломятся.

BrokenBrake:
Я, кстати, файлы вообще не открываю. Эта сгенерированная статистика инклюдится, там в файле сразу массив в переменной.

Имхо: мемкэшед, временные таблицы mysql, sqllite - как вариант если не хочется возиться с файлами непосредственно. Плюс в первых 2 случаях скорость может оказаться выше.

p.s.: и еще замечание. сериализация работает быстрее чем var_export. и проще отлавливаются ошибки, если файл не полный.

Разработка крупных и средних проектов. Можно с криптой. Разумные цены. Хорошее качество. Адекватный подход. Продаем lenovo legion в спб, дешевле магазинов, новые, запечатанные. Есть разные. skype: edogssoft
BrokenBrake
На сайте с 03.03.2007
Offline
194
#2

edogs, разве информация при file_put_contents не целиком пишется?

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

BrokenBrake добавил 28.10.2009 в 06:16

Ой, вы ответили уже, оказывается.

Тема не обновляется, когда правите сообщение.

Я вас понял, спасибо. Но понял не вполне :)

Значит ли это, что для использования блокировки придётся отказываться от удобнейших file_get_contents и file_put_contents? В мануале сказано:

flock() применяется к handle , который должен быть указателем на открытый файл.

Я, кстати, файлы вообще не открываю. Эта сгенерированная статистика инклюдится, там в файле сразу массив в переменной.

BrokenBrake добавил 28.10.2009 в 06:23

И ещё очень важный момент из мануала:

http://docs.php.net/manual/ru/function.flock.php
В некоторых операционных системах flock() реализован на уровне процессов. При использовании многопоточных серверных API, таких как ISAPI, вы не можете полагаться на flock() для защиты ваших файлов от дугих PHP-скриптов, которые работают в параллельном потоке на том же сервере!

Если несколько пользователей открыли один и тот же PHP-файл, который пишет в другой файл... наверно, блокировка не поможет? Не понимаю :(

BrokenBrake добавил 28.10.2009 в 06:28

edogs:
Имхо: мемкэшед, временные таблицы mysql, sqllite - как вариант если не хочется возиться с файлами непосредственно. Плюс в первых 2 случаях скорость может оказаться выше.

Я про временные таблицы даже не знал ничего.

Изучу этот вопрос, спасибо!

edogs:
p.s.: и еще замечание. сериализация работает быстрее чем var_export. и проще отлавливаются ошибки, если файл не полный.

Сперва именно сериализацию и делал, но было хуже.

BrokenBrake
На сайте с 03.03.2007
Offline
194
#3

Огромное спасибо за помощь Edogs, и Aktuba, а также моим клиентам, которые провели экстремальное тестирование. Сегодня я устранил проблему. Если кто-то работает с данными в файлах, настоятельно рекомендую ознакомиться вот с этой заметкой - http://airbase.ru/computers/php/flock/ (в данный момент недоступна)

Главное оттуда:

Т.е. делаем так:

$fh=fopen($file, "a+"); // это если ещё и читать надо.
// Если только писать - то достаточно "a"
flock($fh); // блокируем файл.
fseek($fh,0); // переходим в начало.
fread(...); // читаем, если надо.
...
ftruncate($fh,0); // режем/трём файл по нулям.
fwrite(...); // пишем что надо
fclose($fh);

Это работает без сбоев месяцами при тысячах обращений к файлу в день.

Следует также помнить, что читать файл нужно только через fopen() (можно fopen(..","r")) НО НЕ ЧЕРЕЗ file() или readfile(). Может считаться полузаписанный файл. Т.е. если это только для разового чтения и сбой не страшен, то пожалуйста. Если же требуется что-то прочитать, изменить и записать, то всё надо делать в одно открытие файла, как в приведённом выше примере.
N
На сайте с 06.05.2007
Offline
419
#4

Блокировка не нужна если есть атомарная операция переименования файла.

Создаете новый файл с кешем, не стирая старый и делаете rename(). Полностью избавляет от необходимости ставить блокировки чтения.

Впрочем, нужно помнить, что на windows-хостинге rename не удаляет старый файл с тем же именем автоматически. Но таким хостингом никто из пхпшников не пользуется.

Кнопка вызова админа ()
BrokenBrake
На сайте с 03.03.2007
Offline
194
#5
netwind:
Блокировка не нужна если есть атомарная операция переименования файла.
Создаете новый файл с кешем, не стирая старый и делаете rename(). Полностью избавляет от необходимости ставить блокировки чтения.

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

S
На сайте с 15.01.2008
Offline
34
#6

Советую для вышеописанных целей использовать memcached (http://ru.wikipedia.org/wiki/Memcached), для Ваших целей как в плане экономия ресурсов, так и в плане скорости подойдет идеально.

Качественный хостинг Unlimits Telecom (http://www.unlimits.ru) (ООО "БизнесТелеКом"). Официальный Twitter канал (http://twitter.com/untelecom). Ознакомиться с нашими услугами можно в этом (/ru/forum/478822) топике.
BrokenBrake
На сайте с 03.03.2007
Offline
194
#7

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

N
На сайте с 06.05.2007
Offline
419
#8

BrokenBrake, а никаких минусов нет, кроме windows. Если вспомните - напишите.

DeveloperRu
На сайте с 27.02.2009
Offline
72
#9

насколько я изучил документацию, можно использовать LOCK_EX в int file_put_contents ( string $filename , mixed $data [, int $flags = 0 [, resource $context ]] )

Описано это так:

LOCK_EX Acquire an exclusive lock on the file while proceeding to the writing.

Ответы на вопросы (http://telenok.com)
dvaes
На сайте с 03.09.2007
Offline
65
#10

слушайте netwind'а )

у флока минусов по-больше, чем с временным файлом и переименовыванием)

123 4

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий