Реализация кэширования на PHP

Приветсвую тебя, дорогой читатель. В этой заметке я хочу поведать тебе, как можно элегантно чистить кэш Varnish. Данная статья описывает, как можно удалять страницы=объекты из кэша, используя их URL адреса.

Итак для начала нужно описать ACL в настройках нашего хоста, что бы разрешить очистку кэша с определенных ip адресов. Для этого добавим следующее в файл /etc/varnish/default.vcl. (имя файла может отчиаться в зависимости от настройки Вашего сервера)

Acl purge { "localhost"; "public_ip_address";}

If (req.request == "PURGE") { if (!client.ip ~ purge) { error 405 "Not allowed."; } else { purge_url(req.url); error 200 "Purged. Everything is fine"; } }

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

If (req.http.host == "www.your_site.com" && req.url == "^/varadm/.*.(html|php)$") {
return (pass);
}

Для того чтобы исключить из кэширования POST запросы, удостовертесь что в vcl_recv есть вот такие строчки:

If (req.request == "POST") { return (pass); }

Отключаем кеширование для запросов basic авторизации (vcl_recv):

If (req.http.Authorization || req.http.Authenticate) { return (pass); }

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

Sub vcl_error { set obj.http.Content-Type = "text/html; charset=utf-8"; synthetic {" "}; return (deliver); }

Purge Varnish cache

Makes Varnish purge the supplied URL from its cache

">

Следующий - purge.php с вот таким содежанием:

"; if (!$fp) { echo "$errstr ($errno)
n"; } else { $out = "PURGE /$url HTTP/1.0rn"; $out .= "Host: $hostrn"; $out .= "Connection: Closernrn"; fwrite($fp, $out); while (!feof($fp)) { echo fgets($fp, 128); echo "
"; } fclose($fp); echo "" . $host . $url . " was purged

"; echo "Return to varnish admin page"; } echo ""; ?>

Создаем настройки для нашей папки в каталоге Apache: /etc/httpd/conf.d/varadm.conf

Alias /varadm /var/www/varadm DirectoryIndex index.html Options -Indexes +Includes Order allow,deny AuthType Basic AuthUserFile /var/www/varadm/.ok_user AuthGroupFile /dev/null AuthName "Enter username/password" Require valid-user Satisfy any Deny from all

Осталось создать пользователя для базовой авторизации и сгенерировать для него пароль:

Htpasswd -cmb /var/www/varadm/.ok_user user password

Теперь можно заходить на свой сайт, указывая location /varadm:
www.your_site.com/varadm

В форме будет два поля. Одно - URL, второе принимает значение www.your_site.com . В поле URL вставляем адрес объекта, который нужно удалить из кэша и жмем «Submit». Все. Объект удален.

Как ни странно, Varnish кэширует отдельно html код страниц и отдельно создает объекты кэша для статических файлов. Тоесть, если Вы сменили код генерации станицы и удалили ее объект из кэша, это еще не значит что кэш очистился для всех статичесикх объектов, которые присутствуют на этой странице. Получается довольно круто: не нужно очищать кэш для тяжелых страниц при смене одной картинки. Можно грохнуть объект кэша именно для этой картинки.

Приветствую тебя, дорогой читатель. В этой заметке я хочу поведать тебе, как можно элегантно чистить кэш Varnish. Данная статья описывает, как можно удалять страницы=объекты из кэша, используя их URL адреса.

Итак для начала нужно описать ACL в настройках нашего хоста, чтобы разрешить очистку кэша с определенных ip адресов. Для этого добавим следующее в файл /etc/varnish/default.vcl. (имя файла может отличаться в зависимости от настройки Вашего сервера)

Acl purge { "localhost"; "public_ip_address";}

If (req.request == "PURGE") { if (!client.ip ~ purge) { error 405 "Not allowed."; } else { purge_url(req.url); error 200 "Purged. Everything is fine"; } }

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

If (req.http.host == "www.your_site.com" && req.url == "^/varadm/.*\.(html|php)$") { return (pass); }

Для того чтобы исключить из кэширования POST запросы, удостовертесь что в vcl_recv есть вот такие строчки:

If (req.request == "POST") { return (pass); }

Отключаем кеширование для запросов basic авторизации (vcl_recv):

If (req.http.Authorization || req.http.Authenticate) { return (pass); }

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

Sub vcl_error { set obj.http.Content-Type = "text/html; charset=utf-8"; synthetic {" "}; return (deliver); }

Purge Varnish cache

Makes Varnish purge the supplied URL from its cache

">

Следующий - purge.php с вот таким содержанием:

"; if (!$fp) { echo "$errstr ($errno)
\n"; } else { $out = "PURGE /$url HTTP/1.0\r\n"; $out .= "Host: $host\r\n"; $out .= "Connection: Close\r\n\r\n"; fwrite($fp, $out); while (!feof($fp)) { echo fgets($fp, 128); echo "
"; } fclose($fp); echo "" . $host . $url . " was purged

"; echo "
Return to varnish admin page"; } echo ""; ?>

Создаем настройки для нашей папки в каталоге Apache: /etc/httpd/conf.d/varadm.conf

Alias /varadm /var/www/varadm DirectoryIndex index.html Options -Indexes +Includes Order allow,deny AuthType Basic AuthUserFile /var/www/varadm/.ok_user AuthGroupFile /dev/null AuthName "Enter username/password" Require valid-user Satisfy any Deny from all

Осталось создать пользователя для базовой авторизации и сгенерировать для него пароль:

htpasswd -cmb /var/www/varadm/.ok_user user password

Теперь можно заходить на свой сайт, указывая location /varadm:
http://www.your_site.com/varadm

В форме будет два поля. Одно - URL, второе принимает значение www.your_site.com. В поле URL вставляем адрес объекта, который нужно удалить из кэша и жмем "Submit". Все. Объект удален.

Как ни странно, Varnish кэширует отдельно html код страниц, и отдельно создает объекты кэша для статических файлов. То есть, если Вы сменили код генерации станицы и удалили ее объект из кэша, это еще не значит что кэш очистился для всех статических объектов, которые присутствуют на этой странице. Получается довольно круто: не нужно очищать кэш для тяжелых страниц при смене одной картинки. Можно грохнуть объект кэша именно для этой картинки.

При создании статьи использовались следующие материалы:
Varnish vcl reference
Script to purge varnish cache
Exploring methods to purge varnish cache

(Visited 644 times, 1 visits today)

(PHP 4, PHP 5, PHP 7)

clearstatcache — Очищает кеш состояния файлов

Описание

clearstatcache ([ bool $clear_realpath_cache = FALSE [, string $filename ]]) : void

Для обеспечения большей производительности при использовании функций stat() , lstat() или любой другой функции, перечисленных в приведенном ниже списке, PHP кеширует результаты их выполнения. Однако, в некоторых случаях вам может потребоваться очистка этого кеша. Например, когда ваш скрипт несколько раз проверяет состояние одного и того же файла, который может быть изменен или удален во время выполнения скрипта, вы можете захотеть очистить кеш состояния. В этом случае необходимо использовать функцию clearstatcache() для очистки в PHP кешированной информации об указанном файле.

Обратите внимание, что PHP не кеширует информацию о несуществующих файлах. Так что, если вы вызовете file_exists() на несуществующем файле, она будет возвращать FALSE до тех пор, пока вы не создадите этот файл. Если же вы создадите файл, она будет возвращать TRUE , даже если затем вы его удалите. Однако, функция unlink() очистит данный кеш автоматически.

Замечание :

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

Список функций, результаты выполнения которых кешируются: stat() , lstat() , file_exists() , is_writable() , is_readable() , is_executable() , is_file() , is_dir() , is_link() , filectime() , fileatime() , filemtime() , fileinode() , filegroup() , fileowner() , filesize() , filetype() и fileperms() .

Список параметров

clear_realpath_cache

Очищать кеш realpath или нет.

Filename

Очистить кеш realpath и stat только для определенного файла, используется только если параметр clear_realpath_cache установлен в TRUE .

Возвращаемые значения

Эта функция не возвращает значения после выполнения.

Список изменений

Примеры

Пример #1 Пример использования clearstatcache()

$file = "output_log.txt" ;

function get_owner ($file )
{
$stat = stat ($file );
$user = posix_getpwuid ($stat [ "uid" ]);
return $user [ "name" ];
}

$format = "UID @ %s: %s\n" ;

Chown ($file , "ross" );
printf ($format , date ("r" ), get_owner ($file ));

Clearstatcache ();
printf ($format , date ("r" ), get_owner ($file ));
?>

apcu vs (16)

Мне нужно очистить все записи кэша APC при развертывании новой версии сайта. APC.php имеет кнопку для очистки всех кеш-кодов операций, но я не вижу кнопок для очистки всех пользовательских записей или всех записей системы или всех записей в каждом каталоге.

Можно ли очистить все записи кэша через командную строку или каким-либо другим способом?

Answers

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

Например, в случае Centos / RedHat Linux:

Sudo service httpd graceful

Sudo service apache2 graceful

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

Это не решит вашу проблему для всех записей кэша, если вы используете скрипт apc.php на складе, но он может вызвать адаптированный сценарий или другой, который вы создали.

Это очищает кеш-код операции:

Curl --user apc:$PASSWORD "http://www.example.com/apc.php?CC=1&OB=1&`date +%s`"

Измените параметр OB на 3, чтобы очистить кеш пользователя:

Curl --user apc:$PASSWORD "http://www.example.com/apc.php?CC=1&OB=3&`date +%s`"

Поместите обе строки в скрипт и вызовите его с помощью $ PASSWORD в вашем env.

Если вы хотите отслеживать результаты через json, вы можете использовать этот скрипт:

Как уже упоминалось в других ответах, этот скрипт должен быть вызван через http или curl, и вам нужно будет защитить его, если он будет открыт в корневом каталоге вашего приложения. (через ip, токен...)

Я не думаю, что любой из этих ответов действительно работает для очистки кэша APC от командной строки. Как заметил Фрэнк Фармер , CLI работает в процессе, отличном от Apache.

Мое решение для очистки из командной строки состояло в том, чтобы написать сценарий, который копирует сценарий очистки APC в web каталог и получает к нему доступ, а затем удаляет его. Сценарий ограничен доступом к локальному хосту.

    apc_clear.php

    Это файл, который скрипт копирует в веб-каталог, получает доступ и удаляет.

    true)); } else { die("SUPER TOP SECRET"); }

    Сценарий очистки кеша

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

    Copy($apcPaths["data"], $apcPaths["web"]); //"data" is a non web accessable directory $url = "http://localhost/apc_clear.php"; //use domain name as necessary $result = json_decode(file_get_contents($url)); if (isset($result["success"]) && $result["success"]) { //handle success } else { //handle failure } unlink($apcPaths["web"]);

Вы можете использовать функцию PHP apc_clear_cache .

Вызов apc_clear_cache() очистит системный кеш, и вызов apc_clear_cache("user") очистит кеш пользователя.

Как определено в документе APC:

Чтобы очистить кеш-прогон:

Php -r "function_exists("apc_clear_cache") ? apc_clear_cache() : null;"

Хорошим решением для меня было просто не использовать устаревший пользовательский кеш после развертывания.

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

  1. Не используйте устаревшие записи кэша после развертывания только обновленных структур
  2. Не очищайте весь кеш при развертывании, чтобы не замедлить свою страницу.
  3. Некоторые старые кэшированные записи могут быть повторно использованы после восстановления вашего развертывания (если записи не были автоматически удалены)
  4. APC удалит старые записи кэша после истечения срока действия ИЛИ при нехватке кеша

Это возможно только для кеша пользователя.

Это не указано в документации, но очистить кеш-код операции, который вы должны выполнить:

Apc_clear_cache("opcode");

EDIT: похоже, это относится только к некоторым более старым версиям APC.

Независимо от того, какую версию вы используете, вы не можете очистить кеш APC mod_php или fastcgi от скрипта php cli, поскольку скрипт cli будет запускаться из другого процесса как mod_php или fastcgi. Вы должны вызвать apc_clear_cache () из процесса (или дочернего процесса), для которого вы хотите очистить кеш. Одним из таких подходов является использование curl для запуска простого скрипта php.

apc_clear_cache () работает только в одном и том же php SAPI, который вы хотите очистить. Если у вас есть PHP-FPM и вы хотите очистить кэш apc, вы делаете это через один из php-скриптов, а не в командной строке, потому что два кэша разделены.

У нас была проблема с APC и символическими ссылками на символические ссылки на файлы - она, похоже, игнорирует изменения в самих файлах. Как-то помогло прикосновение к файлу. Я не могу сказать, в чем разница между модификацией файла и касанием его, но почему-то это было необходимо...

apc.stat = "1" заставит APC статировать (проверять) скрипт по каждому запросу, чтобы определить, было ли оно изменено. Если он был изменен, он будет перекомпилировать и кэшировать новую версию.

Если этот параметр выключен, APC не будет проверять, что обычно означает, что для принудительной проверки APC необходимо перезапустить веб-сервер или очистить кеш вручную. Обратите внимание, что конфигурации веб-сервера FastCGI могут не очищать кеш при перезагрузке. На производственном сервере, где файлы сценариев редко меняются, значительное повышение производительности может быть достигнуто с помощью отключенных статистических данных.

Если вы работаете в стеке NGINX / PHP-FPM, лучшим вариантом является, вероятно, просто перезагрузка php-fpm

service php-fpm reload (или любая ваша команда перезагрузки может быть в вашей системе)

если вы запустите fpm под ubuntu, вам нужно запустить код ниже (отмечен 12 и 14)

Service php5-fpm reload

Моя работа для сборки Symfony с получением экземпляров на одном сервере:

Шаг 1. Создайте триггер или что-то, чтобы установить флаг файла (например, команду Symfony), затем создайте marker file .

File_put_contents("clearAPCU","yes sir i can buggy")

Шаг 2. В файл индекса при запуске добавьте код очистки и удалите marker file .

If(file_exists("clearAPCU")){ apcu_clear_cache(); unlink("clearAPCU"); }

Шаг 2. Запустите приложение.

В новом интерфейсе APC Admin есть опции для добавления / очистки кеша пользователя и кэша операций, одна интересная функция заключается в добавлении / обновлении / удалении каталога из кэша opCode

Прочитав этот учебник, я попытался реализовать его в своей программе.

У меня есть 4-5 файлов, содержащих адреса. Каждый файл содержит около 30 миллионов записей. Я использую ту же конфигурацию, которую вы предлагаете, но мой номер INSERT в секунду является низким (~ 10.000 записей в секунду).

Здесь ваше предложение терпит неудачу. Вы используете одну транзакцию для всех записей и одну вставку без ошибок / сбоев. Предположим, что вы разбиваете каждую запись на несколько вставок в разных таблицах. Что произойдет, если запись будет нарушена?

Команда ON CONFLICT не применяется, потому что если у вас есть 10 элементов в записи, и вам нужно, чтобы каждый элемент был вставлен в другую таблицу, если элемент 5 получает ошибку CONSTRAINT, тогда все предыдущие 4 вставки тоже должны идти.

Таким образом, здесь происходит откат. Единственная проблема с откатом заключается в том, что вы теряете все свои вставки и начинаете с вершины. Как вы можете это решить?

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

Это решение помогло мне обойти проблемы, которые у меня возникают при работе с файлами, содержащими плохие / дублированные записи (у меня было почти 4% плохих записей).

Созданный мной алгоритм помог мне сократить мой процесс на 2 часа. Окончательный процесс загрузки файла 1hr 30m, который все еще медленный, но не сравнимый с 4hrs, который он первоначально взял. Мне удалось ускорить вставку с 10.000 / с до ~ 14.000 / с

Если у кого-то есть другие идеи о том, как ускорить это, я открыт для предложений.

ОБНОВЛЕНИЕ :

В дополнение к моему ответу выше, вы должны иметь в виду, что вставки в секунду зависят от жесткого диска, который вы используете. Я тестировал его на трех разных ПК с разными жесткими дисками и получал огромные различия во времени. PC1 (1 час 30 м), PC2 (6 часов) PC3 (14 часов), поэтому я начал задаваться вопросом, почему бы это было так.

После двух недель исследований и проверки нескольких ресурсов: Hard Drive, Ram, Cache, я узнал, что некоторые настройки на вашем жестком диске могут повлиять на скорость ввода-вывода. Нажимая свойства на желаемом выходном диске, вы можете увидеть два варианта на общей вкладке. Opt1: Сжатие этого диска, Opt2: Разрешить файлу этого диска индексировать содержимое.

Отключив эти два варианта, все 3 компьютера теперь занимают примерно одно и то же время для завершения (1 час и от 20 до 40 минут). Если вы сталкиваетесь с медленными вставками, проверьте, настроен ли ваш жесткий диск с этими параметрами. Это сэкономит вам много времени и головных болей, пытаясь найти решение