Сайт о телевидении

Сайт о телевидении

» » Кэширование данных страниц в php

Кэширование данных страниц в php

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

Что такое кэширование?

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

На сегодняшний день кэши бываю двух типов - локальные и общие.

  • Локальный - кеш, хранимый на диске у клиента, создаваемый, а также управляемый его интернет-браузером.
  • Общий - это кэш прокси-сервера провайдера, он может состоять из одного или ряда прокси-серверов.

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

Для динамических страничек, которые создаются в результате работы PHP-приложения, казалось бы, кэширование весьма вредно. Содержание странички формируются по запросу пользователя на основе определенного источника информации. Тем не менее, кэширование бывает полезным. Управляя им можно сделать работу с вашим сервером гораздо удобнее для пользователя, разрешая загрузку из кэш конкретных страниц, предотвращая таким образом их повторную выгрузку с сервера и экономя пользователю трафик и время.

Ключевые принципы сохранения страниц в кэш

PHP-приложение может управлять кэшированием результатов его работы формируя дополнительные поля в заголовке HTTP ответа вызовом специальной функции Header().

Несколько общих утверждений, которые характерны не только для PHP-приложений:

  • Странички, которые передаются по POST не сохраняются в кэш никогда.
  • Странички, которые запрашиваются по GET и содержат параметры (в URL есть "?") не сохраняются в кэш, в случае если не указано обратное.

В большинстве ситуаций каких-то дополнительных инструкций в приложение добавлять не нужно. Основные нюансы, на которые надо обратить внимание:

  • запрет кэширования документов, которые кэшируются по умолчанию;
  • кэширование документов, которые не подлежат кэшированию по умолчанию.

Запрет на кэширования документов (которые кэшируются по умолчанию)

Эта задача возникает для PHP-скриптов, которые вызываются без параметров или являются индексами директорий, но формируют информацию персонально под пользователя (к примеру на основе user agent или же cookies) или работают на основе быстро изменяющихся сведений. Мы по спецификации HTTP/1.1 можем управлять такими полями:

  1. Expires - задает дату истечения срока годности определенного документа. Задание ее в прошлом определяет запрет кэш для этой странички.
  2. Cache-control: no-cache - управление кэшем. Значение no-cache определяет запрет кэш этой странички. Для версии протокола HTTP/1.0 здесь действует "Pragma: no-cache".
  3. Last-Modified - это дата последнего изменения определенного содержимого. Поле применяется исключительно для статических страничек. Apache заменяет данное поле значением поля Date для динамически генерируемых страничек, в частности для страниц, которые содержат SSI.

Чтобы запретить кэширование, достаточно прописать:

Для того, чтобы документ пометить как "устаревший", необходимо установить Expires равным полю Date.

Header("Expires: " . gmdate("D, d M Y H:i:s") . " GMT");

Не следует также забывать о том, что формы, которые запрошены по POST кэшированию не подлежат.

Кэширование с прогнозируемым обновлением

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

Главной задачей здесь является получить дату следующего понедельника в виде RFC-1123.

$dt_tmp=getdate(date("U")); header("Expires: " . gmdate("D, d M Y H:i:s", date("U")-(86400*($dt_tmp["wday"]-8))) . " GMT"); header("Cache-control: public");

Данным способом можно очень эффективно управлять поведением странички в кэш. Можно выделить особые временные интервалы в течении которых содержание определенной странички остается постоянным.

Другой подход, который применяется при более оперативном обновлении данных и одновременной большой посещаемости сервера (в другом случае кэширование эффективным не будет) состоит в использовании специального заголовка Cache-control: max-age=секунды, который определяет время, по истечении которого документ уже считается устаревшим и имеющий гораздо больший приоритет при вычислении свежести конкретного документа.

Если Вы публикуете новости с интервалом в 60 минут:

Header("Cache-control: public"); header("Cache-control: max-age=3600");

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

Вам необходимо создать два специальных файла. Первый будет делать вывод кэша, а второй - создавать кэш.

Начнем с первого файла, который назовем read_cache.php .

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

Теперь создадим специальный файл write_cache.php . Он будет записывать в файл то, что накопилось в буфере.

Теперь в любом php-файле, который отвечает за вывод, можно включить кэширование:

Теперь вы можете все проблемные странички начать кэшировать. Однако не забывайте, пока кэш живет, пользователь не будет видеть любые обновления. В связи с этим, делайте кэширование на PHP лишь для тех страниц, которые очень редко обновляются.

  • Перевод

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

Существует множество библиотек для такого кэширования, например, APC , XCache , eAccelerator и Zend Platform .

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

/**
* Compile Files for APC
* The function runs through each directory and
* compiles each *.php file through apc_compile_file
* string $dir start directory
* void
*/
function compile_files($dir)
{
$dirs = glob($dir. DIRECTORY_SEPARATOR. "*", GLOB_ONLYDIR);
if (is_array($dirs) && count($dirs) > 0)
{
while(list(,$v) = each($dirs))
{
compile_files($v);
}
}
$files = glob($dir. DIRECTORY_SEPARATOR. "*.php");
if (is_array($files) && count($files) > 0)
{
while(list(,$v) = each($files))
{
apc_compile_file($v);
}
}
}
compile_files("/path/to/dir");

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

if (!$config = apc_fetch("config"))
{
require("/path/to/includes/config.php");
apc_store("config", $config);
}

Практический пример иллюстрируется на базе использования Zend Framework и простого запуска утилиты ab, в данном примере результат XML-конфигурации сохраняется в кэше. Ускорение времени разбора позволяет экстремально быстро получить доступ к параметрам конфигурации.
Код:
if (!$conf = apc_fetch("pbs_config"))
{
$conf = new Zend_Config_Xml(PB_PATH_CONF. "/base.xml", "production");
apc_store("pbs_config", $conf);
}

Команда для теста ab -t30 -c5 www.example.com
Результат без кэширования
Concurrency Level: 5
Time taken for tests: 30.33144 seconds
Complete requests: 684
Failed requests: 0
Write errors: 0

Результат с кэшированием
Concurrency Level: 5
Time taken for tests: 30.12173 seconds
Complete requests: 709
Failed requests: 0
Write errors: 0

Как вы видите, мы получили около 3-4% в производительности, закэшировав значения конфигурационного файла. Существует много других мест, которые также можно оптимизировать, нахождение таких мест позволит увеличит количество обработанных запросов.

Файловое кэширование результатов
В некоторых случаях сервер обрабатывает запросы, результатом которых является одинаковый контент. Есть возможность закэшировать подобные вид контента (полностью или его часть)
В данном тексте иллюстрируется пример на основе пакета Pear::Cache_Lite .

Полное кэширование вывода
Полное кэширование довольно тяжело выполнить на большинстве сайтов с постоянно обновляющимися данными из большого количества источников. Все это правда, однако, нет необходимости обновлять данные каждую секунду. Даже 5-10 минутная задержка при экстремально высокой загрузке сайта позволит вам увеличить производительность.
Пример ниже, сохраняет слепок страницы для будущего использования. Такой подход может помочь большому количеству пользователей.
Я не рекомендую использовать данное решение, но если вам нужно что-то быстрое, вы можете его использовать, рано или поздно вы увидите недостатки этого метода.
The Bootstrap Cache Example:

require("/path/to/pear/Cache/Lite/Output.php");
$options = array(
"cacheDir" => "/tmp/",
"lifeTime" => 10
);

if (!($cache->
{
require("/path/to/bootstrap.php");
$cache->end();
}

Пример на основе.htaccess:
.htaccess
php_value auto_prepend_file /path/to/cache_start.php
php_value auto_append_file /path/to/cache_end.php
cache_start.php
require("Cache/Lite/Output.php");

$options = array(
"cacheDir" => "/tmp/",
"lifeTime" => 10
);
$cache = new Cache_Lite_Output($options);
if (($cache->start($_SERVER["REQUEST_URI"])))
exit;

Cache_end.php
$cache->end();


Cache Lite делает большинство тяжелой работы такой как блокирование файла, решение как сохранять контент для различных параметров (в данном примере используется REQUEST URI). Вам также может быть необходимы значения $_POST, $_COOKIE и $_SESSION.

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

require("Cache/Lite.php");
$options = array(
"cacheDir" => "/tmp/",
"lifeTime" => 3600 //1 hour
);

if (!($categories = $cache->get("categories")))
{

$categories = "";
$cache->save($categories, "categories");
}
echo $categories;

Пока это чересчур упрощенный пример, он только показывает гибкость сохранения значения. Вы можете сохранять значения массивов для того чтобы обращаться к ним позже.
Кэширования значения массива
require("Cache/Lite.php");
$options = array(
"cacheDir" => "/tmp/",
"lifeTime" => 3600, //1 hour
"automaticSerialization" => true
);
$cache = new Cache_Lite($options);
if (!($categories = $cache->get("categories")))
{
$rs = mysql_query("SELECT category_id, category_name FROM category");
$categories = array();
while($row = mysql_fetch_assoc($rs))
{
$categories = $row;
}
$cache->store($categories, "categories");
}
var_dump($categories);

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

Кэширование в оперативной памяти
Существует множетсво путей для того чтобы произвести кэширование в памяти: memcached, memory tables в базах данных, RAM disk и другие.
Memcached
С сайта memcache memcached это высокопроизводительная и распределенная кэширующая система, которая увеличивает скорость динамических веб-приложений путём снижения загрузки с базы данных.
О чем это говорит, о том, что можно сохранить данные на одном сервере, к которому будут обращаться другие сервера, это не зависит от вашего веб-сервера (как в случае кеширования промежуточного кода), так как memcached – это демон, который в большинстве случаев используется для кэширования результатов запросов к базам данных.
Пример работы с Memcache:

$post_id = (int) $_GET["post_id"];
$memcached = new Memcache;
$memcached->connect("hostname", 11211);
if (!$row = $memcached->get("post_id_". $post_id))
{
//yes this is safe, we type casted it already ;)
$rs = mysql_query("SELECT * FROM post WHERE post_id = ". $post_id);
if ($rs && mysql_num_rows($rs) > 0)
{
$row = mysql_fetch_assoc($rs);
// cache compressed for 1 hour
$memcached->set("post_id_". $post_id, $row, MEMCACHE_COMPRESSED, time() + 3600);
}
}
var_dump($row);

Это довольно простой пример работы с memcached. Мы сохранили простой элемент в памяти для будущего использования, до которого в будущем получим лёгкий доступ. Я рекомендую использовать данный метод для данных, к которым вы чаще всего будете обращаться.
Пример настройке параметров сессий для работы с Memcache
session.save_handler = memcache
session.save_path = «tcp://hostname:11211»

Как вы видите поддержка сессий довольно таки простая. Если у вас много серверов memcached переменная save_path должна содержать названия серверов через запятую with each server.
Memory Tables баз данных
Memory tables баз данных могут быть использованы для хранения данных сессии. Вы можете создать таблицу такого типа используя MySQL. Создайте ваш собственный обработчик сессий. Это один из способов увеличить производительность сессий.
RAM Disk
В то время как подход использования оперативной памяти как диска не является примером распределенности, данный подход легко может быть приспособлен для увеличения производительности сайта. Запомните информация находящаяся на таком диске исчезает после перезагрузки сервера.
Создание RAM-диска
mount --bind -ttmpfs /path/to/site/tmp /path/to/site/tmp

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

Надеюсь, что описанное выше было достаточно информативно. Здесь не описан весь потенциал кэширования, например использование кэширования в распределенных базах данных или использование Squid. В будущих статьях я опишу и это…

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

Статические локальные переменные

Быстрым и эффективным способом кэширования результатов функции/метода является использование статических локальных переменных. Рассмотрим пример, который выполняет сложные вычисления:

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

Эта методика кэширования не зависит от внешних расширений и поддерживается на уровне языка. Поскольку статические локальные переменные доступны только в пределах функции, в которой они определены, обновление кэша может быть проблематичным. Как правило, для этого необходимо передать какую-либо логическую переменную $use_cache или использовать вместо них статические переменные класса.

Статические переменные не разделяются между процессами PHP и могут кэшировать только на короткое время – охватывающее время выполнения сценария. Хорошим кандидатом является метод, который много раз вызывается из нескольких мест, например, для хранения состояния пользователя или результата, требующего большого объёма математических расчетов.

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

Функции разделяемой памяти APC

PHP является полу-компилируемым языком, а это значит, что каждый сценарий компилируется непосредственно не в машинный код, а в промежуточный код, известный как набор опкодов(байт-код). Данный шаг компиляции потребляет много ресурсов процессора и должен выполняться каждый раз при выполнении сценария. APC (Alternative PHP Cache) это расширение, которое пропускает этот шаг компиляции за счет кэширования опкодов в памяти.

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

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

Чтобы сделать кэш недействительным, можно использовать значения продолжительности существования (TTL), как в примере выше, или следующие функции:

Другие примечания по поддержке разделяемой памяти в APC:

В конфигурационном INI файле есть директива для ограничения размера кэша. С соответствующими значениями TTL это дает возможность задавать приоритет кэшированным данным, когда в случае достижения предела памяти истекшие/старые значения будут исключены из кэша.

С точки зрения производительности - статические переменные всегда будет быстрее, чем функции apc_fetch/apc_store , поскольку доступ к разделяемой памяти должен быть заблокирован и синхронизирован, чтобы предотвратить конфликтные ситуации.

APC является довольно популярным расширением, и поддерживается основными разработчиками PHP и (весьма вероятно) будет поставляться в комплекте с PHP 5.4.

Memcached для больших распределенных кэшей

Как только сайт начинает получать много посещений, в конечном счете, появляется задача распределения нагрузки между различными машинами. В результате этого обычно требуется переместить PHP на несколько серверов приложений. Если вы использовали APC кэширование раньше - каждый сервер приложений теперь имеет отдельный и дублирующий кэш.

Memcached с другой стороны, представляет собой распределенную службу для хранения данных ключ-значение. Расширение может быть развернуто на отдельном выделенном сервере или в том же стеке PHP приложений. Важно понимать, что нет никакой синхронизации/репликации между несколькими Memcached серверами, и они совсем ничего не знают друг о друге. Фактический сервер, который будет использоваться для хранения, выбирается на стороне клиента с помощью алгоритма хеширования на основе предоставленных данных "ключа". Именно поэтому, в отличие от APC, кэшированные данные не дублируются между различными машинами, а память лучше используется для крупных распределенных приложений.

API очень похож на функциональность разделяемой памяти в APC. Тот же пример с обменом валют, реализованный с помощью PHP расширения Memcache:

pconnect("..."); function getCurrencyRates() { global $memcache; $rates = $memcache->get("rates"); if ($rates === false) { // Запрос к базе данных или внешним API функциям $rates = ...; // Курс обмена будет кэширован на 1 час $memcache->set("rates", $rates, 0, 3600); } return $rates; } ?>

Обновление кэша такое же, как и в APC – с использованием TTL функциональности или набора функций.

delete("rates"); // Удаляет кэш $rates $memcache->flush(); // Удаляет все кэшированные данные?>

Локальный APC кэш всегда будет более быстрым методом по сравнению с Memcached.

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

Таблицы баз данных в оперативной памяти

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

MySQL предоставляет таблицы в оперативной памяти в подсистеме хранения данных MEMORY. Хотя данные будут очищены после перезагрузки сервера - схемы таблиц будут сохраняться:

CREATE TABLE test (...) ENGINE = MEMORY

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

CREATE TEMPORARY TABLE test (...)

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

true)); ?>

Так что же можно сделать с таблицей в оперативной памяти? Хотя такая таблица никогда не будет быстрее доступа к данным ключ-значение в APC/Memcached, вы получаете мощь SQL. Кэшированные данные могут быть отфильтрованы, упорядочены, сгруппированы и даже объединены с другими данными в таблицах.

Простой файловый кэш

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

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

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

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

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

  • Кэширование готовых страниц - страница генерируется php, а потом пользователю отдается готовая страница без обращения к php. Я расскажу как это сделать через fastcgi, но не рекомендую применять такой метод для wordpress или других движков, их лучше кэшировать с помощью специальных плагинов;
  • Кэширование байт кода и инструкций - а это уже интересно, кэшируется не вся страница, а только некоторые инструкции, и куски байт кода, которые не изменяются при вызовах скрипта. Перед тем как выполнять скрипт, интерпретатор должен преобразовать его в понятный для него формат, при кэшировании такое преобразование выполняется только первый запуск, а дальше берется версия из кэша;
  • Кэширование сессий - по умолчанию php сохраняет сессии пользователей в файлы и мы можем немного ускорить его работу, если будем сохранять сессии в оперативную память.

Кэширования байткода в PHP

Начиная с PHP 5.5 в интерпретатор языка была добавлена поддержка кэширования байткода из ZendFramework. В новых версиях этот кэш позволяет очень сильно увеличить производительность вашего ресурса, например, есть сведения, что на PHP 7 Wordpres и другие движки работают чуть ли не в два раза быстрее. Перед тем как настраивать кєширование opcode php, нужно установить его пакет:

sudo apt install php-opcache

Или для Red Hat дистрибутивов:

sudo yum install php-opcache

Затем, чтобы включить кэширование нужно добавить несколько строк в php.ini, можно также создать отдельный файл в /etc/php/conf.d/

vi /etc/php.d/opcache.ini

zend_extension=opcache.so;
opcache.error_log=/var/log/php-fpm/opcache-error.log
opcache.enable=1;
opcache.memory_consumption=256;
opcache.interned_strings_buffer=8;
opcache.max_accelerated_files=4000;
opcache.revalidate_freq=180;
opcache.fast_shutdown=0;
opcache.enable_cli=0;
opcache.revalidate_path=0;
opcache.validate_timestamps=2;
opcache.max_file_size=0;
opcache.file_cache= /var/www/сайт/opcache;

Рассмотрим что означают эти строки, чтобы вы знали какие значения установить. Первая строка загружает расширение, здесь ничего менять не нужно.

  • opcache.error_log - указывает файл для записи лога ошибок, будет полезно при отладке;
  • opcache.log_verbosity_level - указывает насколько подробным должен быть лог файл, значение от 1 до 4;
  • opcache.enable - включает кэширование;
  • opcache.enable_cli - включает кэширование страниц php для консольной версии;
  • opcache.memory_consumption - количество оперативной памяти для хранения кэша;
  • opcache.max_accelerated_files - число скриптов/файлов, которые нужно кэшировать;
  • opcache.validate_timestamps - проверять время изменения данных в файле скрипта;
  • opcache.revalidate_freq - частота проверки для предыдущего параметра;
  • opcache.revalidate_path - установите в 0 чтобы выполнять проверку при include только первый раз;
  • opcache.enable_file_override - кэширует запросы к атрибутам файлов, например, существование и т д;
  • opcache.blacklist_filename - список файлов, которые не нужно кэшировать;
  • opcache.max_file_size - максимальный размер файла скрипта для кэширования, 0 - не ограниченно;
  • opcache.interned_strings_buffer - допустимое количество строк в буфере;
  • opcache.fast_shutdown - использовать быстрый способ освобождения памяти.

После сохранения всех настроек вам останется только перезапустить php или ваш веб-сервер:

systemctl restart php-fpm

Для того чтобы убедиться, что все работает вы можете захотеть посмотреть какие скрипты уже закэшированы. Для этого можно использовать скрипт opcache-status . Просто сохраните скрипт в директорию веб-сервера, а затем дайте ему права:

chmod 777 /var/www/сайт/opcode.php

http://localhost/opcache.php

Здесь можно видеть подробную статистику по кєширвоанию, настройки и количество занятой памяти.

Хранение сессий в memcached

По умолчанию php хранит сессии в файловой системе, в некоторых случаях, вы можете достаточно сильно ускорить работу php, если перенесете хранение сессий из файлов в оперативную память, например, memcached. Сначала нужно установить memcached и php библиотеку для работы с ней:

sudo apt install memcached php-memcached

Или для систем на базе Red Hat:

sudo yum install memcached php-memcached

Сначала нам нужно настроить memcached, откройте файл /etc/sysconfig/memcached и найдите строку CACHESIZE, здесь нужно указать объем оперативной памяти, которая выделяется под кэш:

vi /etc/sysconfig/memcached

session.save_handler = memcache
session.save_path = "tcp://localhost:11211"

Осталось перезапустить ваш php интерпретатор:

systemctl restart php-fpm

Если вы хотите проверить все ли правильно кэшируется и есть ли вообще что-либо в кэше, можно использовать phpmemcacheadmin .

Кэширование страниц fastcgi

Я не советую использовать кэширование fastgci для сайтов WordPress, потому что там есть специальные плагины, которые могут точно контролировать кэш, очищать его когда нужно и вовремя обновлять. Но во всех остальных случаях кэш fastcgi может очень сильно ускорить работу сайта. Настраивается он в конфиге, где вы включаете fastgci, например, в конфигурации веб-сервера Nginx. Минимально для настройки кэша fastgci достаточно добавить в блок server такие строки:

vi /etc/nginx/vhosts/site.conf

fastcgi_cache_path /var/nginx/cache levels=1:2 keys_zone=MYAPP:100m inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";

Первая строка настраивает сразу несколько параметров, во первых, она добавляет путь к кэшу, можно использовать любой, только чтобы папка существовала и у веб-сервера были права для записи в нее. Директива levels указывает сколько подпапок будет. Следующая строка указывает что будет использоваться в качестве ключа для кэша. Ключ будет хэширован в md5.

Теперь нужно настроить блок обработки php:

location ~ \.php$ {
fastcgi_pass unix:/var/run/php7-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_cache MYAPP;
fastcgi_cache_valid 200 60m;
}

Здесь мы обращаемся к уже настроенной зоне памяти MYAPP, а также указываем время жизни кэша в один час. Для проверки кэширования можно посмотреть содержимое папки:

ls -lR /var/nginx/cache/

С помощью таких методов ваши страницы будут загружаться намного быстрее. Если вам понадобится отключить кєширование php для отдельных страниц, то сначала создаем переменную no_cache со значением 0:

set $no_cache 0;

Затем проверяем нужные параметры, и если соответствует, то устанавливаем значение в 1:

if ($request_method = POST)
{
set $no_cache 1;
}

И на завершение передаем значение этой переменной таким директивам, это отключит кэширование когда не нужно:

fastcgi_cache_bypass $no_cache;
fastcgi_no_cache $no_cache;

Когда Вы делаете проект, который обладает достаточно проблемными страницами в плане скорости их загрузки, то надо проводить рефакторинг. Но бывают случаи, когда Вы всё написали идеально, однако, скорость оставляет желать лучшего. В таких случаях поможет кэширование страниц . Поэтому я решил написать статью о реализации кэширования на PHP .

Прежде чем показывать код, Вы должны заранее осознать алгоритм. Кэширование - это просто сохранение сгенерированной страницы в отдельный файл . То есть получили HTML-код страницы и сохранили его в отдельный файл. Затем при следующем обращении к скрипту заново страница не генерируется, а берётся HTML-код из этого файла. Разумеется, если при генерации речь может идти даже о десятках секунд (бывает и такое), то здесь речь идёт о сотых долях секунды. Разница очевидна.

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

Начнём с первого файла, который назовём read_cache.php :

$cache_time = 300; // Время жизни кэша в секундах
$file = strrchr($_SERVER["SCRIPT_NAME"], "/");// Получаем название файла
$file = substr($file, 1); // Удаляем слеш
$cache_file = "/cache/$file.html"; // Файл будет находиться, например, в /cache/a.php.html
if (file_exists($cache_file)) {
// Если файл с кэшем существует
if ((time() - $cache_time) < filemtime($cache_file)) {
// Если его время жизни ещё не прошло
echo file_get_contents($cache_file); // Выводим содержимое файла
exit; // Завершаем скрипт, чтобы сэкономить время на дальнейшей обработке
}
}
ob_start(); // Открываем буфер для вывода, если кэша нет, или он устарел
?>

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

Теперь создадим файл write_cache.php , который будет заниматься записью в файл того, что у нас накопилось в буфере:

$handle = fopen($cache_file, "w"); // Открываем файл для записи и стираем его содержимое
fwrite($handle, ob_get_contents()); // Сохраняем всё содержимое буфера в файл
fclose($handle); // Закрываем файл
ob_end_flush(); // Выводим страницу в браузере
?>

И теперь в любом PHP-файле на сайте, отвечающем за вывод страницы, можно включить кэширование следующим образом:

require_once "read_cache.php"; // Пытаемся вывести содержимое кэша
// Здесь идёт обычная генерация страницы
require_once "write_cache.php"; // Здесь идёт сохранение сгенерированной страницы в кэш
?>

Таким образом, теперь Вы можете все свои проблемные страницы начать кэшировать. Но не забывайте, что пока кэш живёт, любые обновления пользователь видеть не будет . Поэтому делайте кэширование на PHP только для тех страниц, которые редко обновляются.