Как написать файл в большом приложении php (несколько вопросов)

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

Могу ли я просто открыть файл и добавить данные. Или я должен открывать, блокировать, писать и разблокировать.

Что будет с файлом, будет работать, и другие данные должны быть написаны. Будет ли эта деятельность потеряна или она будет сохранена. и если это будет сохранено, это остановит приложение.

Если вы были, спасибо за чтение!

+7
источник поделиться
7 ответов

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

+6
источник

Вот простой пример, который подчеркивает опасность одновременных wites:

<?php
for($i = 0; $i < 100; $i++) {
 $pid = pcntl_fork();
 //only spawn more children if we're not a child ourselves
 if(!$pid)
  break;
}

$fh = fopen('test.txt', 'a');

//The following is a simple attempt to get multiple threads to start at the same time.
$until = round(ceil(time() / 10.0) * 10);
echo "Sleeping until $until\n";
time_sleep_until($until);

$myPid = posix_getpid();
//create a line starting with pid, followed by 10,000 copies of
//a "random" char based on pid.
$line = $myPid . str_repeat(chr(ord('A')+$myPid%25), 10000) . "\n";
for($i = 0; $i < 1; $i++) {
    fwrite($fh, $line);
}

fclose($fh);

echo "done\n";

Если добавление было безопасным, вы должны получить файл со 100 строками, все из которых примерно 10 000 символов длинны и начинаются с целого числа. И иногда, когда вы запускаете этот script, это именно то, что вы получите. Иногда несколько добавлений будут конфликтовать, но это будет искажено.

Вы можете найти поврежденные строки с помощью grep '^[^0-9]' test.txt

Это связано с тем, что append файла является только атомарным, если:

  • Вы делаете один вызов fwrite()
  • и что fwrite() меньше, чем PIPE_BUF (где-то около 1-4k)
  • и вы пишете полностью совместимую с POSIX файловую систему.

Если вы сделаете более одного вызова для записи во время добавления журнала или напишите более 4k, все ставки отключены.

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

+9
источник

Если concurrency является проблемой, вы действительно должны использовать базы данных.

+4
источник

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

+1
источник

Это мои 2p.

Если для определенной причины не нужен уникальный файл, я бы не стал добавлять все в огромный файл. Вместо этого я бы обернул файл по времени и размеру. Для этого можно определить пару параметров конфигурации (wrap_time и wrap_size).

Кроме того, я бы, вероятно, представил некоторые буферизации, чтобы избежать ожидания завершения операции записи.

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

+1
источник

Используйте flock()

Смотрите question

0
источник

Если вам просто нужно добавить данные, PHP должен быть в порядке с этим, поскольку файловая система должна заботиться о одновременных добавлениях.

-3
источник

Посмотрите другие вопросы по меткам или Задайте вопрос