Счетчик PHP перекрывает/переполняет только 1 байт данных, счетчик сбрасывается (состояние гонки)

Я знаю, что это простой вопрос, но я скачал скрипт PHP Counter с http://www.stevedawson.com/scripts/text-counter.php

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

Я попытался посмотреть, не испортится ли он, удерживая обновление в моем браузере после того, как 255 запросов переполнились до 0. Как мне исправить этот скрипт? Я думаю, что виновником является filesize(), который, вероятно, получает только 1 байт данных, но это не имеет смысла, поскольку 255 на самом деле 3 bytes данных, верно? так как он сохраняет в текстовом формате?

Почему он переполнится? это даже PHP, он не должен переполняться, просто автоматически мутировать в больший тип данных.

<?php
    $orderCountFile = "order_num_count.txt";
    if (file_exists($orderCountFile)) {
        $fil = fopen($orderCountFile, r);
        $dat = fread($fil, filesize($orderCountFile)); 
        echo $dat+1;
        fclose($fil);
        $fil = fopen($orderCountFile, w);
        fwrite($fil, $dat+1);
    } else {
        $fil = fopen($orderCountFile, w);
        fwrite($fil, 1);
        echo '1';
        fclose($fil);
    }
?>

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

Для исправления, я думаю, мне нужно преобразовать $dat в больший целочисленный тип, но можете ли вы даже преобразовать в PHP?

Кроме того, я думаю, что эти r и w должны быть строками, но они используются как константы, но, похоже, это не вызывает никаких проблем.


person SSpoke    schedule 30.05.2014    source источник
comment
Байт может представлять числа 0-255. en.wikipedia.org/wiki/Byte   -  person Kai    schedule 31.05.2014
comment
Да, я был неправ, он не переполняется, но сбрасывается до 0 ... если вы очень быстро обновляете скрипт ... это, вероятно, проблема гонки чтения / записи, но я все еще не могу понять это.   -  person SSpoke    schedule 31.05.2014
comment
О, я нашел связанный вопрос, вероятно, то же самое stackoverflow.com/questions/5250118/   -  person SSpoke    schedule 31.05.2014


Ответы (1)


Вместо этого используйте file_get_contents и file_put_contents. Вы все еще должны учитывать, что для этого счетчика также существует жесткое ограничение (см. PHP_INT_MAX), но оно значительно выше.

<?php
$file = "counter.txt";
$counter = 0;
if (file_exists($file)) {
  $counter = file_get_contents($file);
}

$counter = $counter + 1;
file_put_contents($file, $counter);
echo $counter;
person Kevin Sandow    schedule 30.05.2014
comment
Я думаю, может ли проблема заключаться в том, что несколько сценариев, работающих одновременно, обращаются к одной и той же файловой системе и вызывают состояние гонки, например, в многопоточности? Кажется, он не останавливается на 255.. Я ошибся, теперь он дошел до 280. Но все равно глючит. - person SSpoke; 31.05.2014
comment
Да, но разве это не условие гонки stackoverflow.com/questions/5250118/ все еще возможно без блокировки файлов file_get_contents/file_put_contents? или они безопасны? - person SSpoke; 31.05.2014
comment
Да, это все еще применимо. Есть возможность предотвратить сброс при добавлении к file_put_contents третьего параметра: флага EX_LOCK. Но вы все равно можете пропустить несколько счетчиков между операцией чтения и записи во время большой нагрузки, в этих случаях счетчик на основе файла может вообще не быть хорошим решением. - person Kevin Sandow; 31.05.2014
comment
Могу ли я заставить другие php-скрипты останавливаться, даже не читая, чтобы не получать устаревшие значения, пока предыдущие не завершатся в любом случае, чтобы сделать это? - person SSpoke; 31.05.2014
comment
Ну, это именно то, что делает решение в связанном посте, если блокирует файл после создания дескриптора, поэтому никакие другие (PHP) процессы не могут прочитать файл до закрытия или разблокировки дескриптора. Но был еще один комментарий, в котором упоминалась база данных для этой операции, поскольку у них уже есть встроенный параллелизм. - person Kevin Sandow; 31.05.2014
comment
Так почему я пропущу несколько хитов, потому что некоторые скрипты будут загружать устаревшие хиты? и сбрасывать другие хиты до устаревшего значения? - person SSpoke; 31.05.2014
comment
Пропущенные попадания были связаны с решением, которое я разместил здесь, но решение вопроса, на который вы ссылались ранее, ничего не пропускает. Я могу только замедлить веб-сервер, потому что несколько процессов могут ожидать доступа к файлу, но это сильно зависит от вашего трафика. - person Kevin Sandow; 31.05.2014
comment
Чем это идеально, я не хочу избегать запуска mysql для чего-то такого простого, чтобы этот скрипт был очень переносимым, с низкой зависимостью от других инструментов, я думаю, я просто приму ваш ответ как правильный, так как я нашел свой ответ. - person SSpoke; 31.05.2014