Сервер: Установка и настройка OPcache и APCu для PHP

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

Старое расширение APC больше не следует устанавливать. Его функции разделены между встроенным в PHP расширением OPcache и пользовательским кешем APCu.

Когда решение не подходит: APCu не заменяет Redis или Memcached в кластере из нескольких серверов. Его данные локальны для конкретного сервера и очищаются при перезапуске PHP-FPM.

Чем отличаются OPcache и APCu

  • OPcache автоматически кеширует скомпилированный PHP-код. Изменять код приложения для его использования не требуется.
  • APCu хранит значения, которые приложение явно записывает через функции apcu_store(), apcu_fetch() или apcu_entry().
  • OPcache ускоряет выполнение PHP-файлов, APCu уменьшает число повторных вычислений и обращений к базе данных.

Проверка текущего окружения

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

php -v
php --ini
php -m | grep -Ei 'Zend OPcache|apcu'

Если OPcache или APCu уже установлены, повторная установка не требуется. Важно убедиться, что команды php и php-fpm относятся к одной версии PHP.

php -v
php-fpm -v

Установка на AlmaLinux

Для обычной модульной установки PHP из репозитория Remi используются пакеты php-opcache и php-pecl-apcu.

sudo dnf install php-opcache php-pecl-apcu

После установки можно посмотреть, какие INI-файлы добавили пакеты:

rpm -ql php-opcache | grep -E '\.ini$'
rpm -ql php-pecl-apcu | grep -E '\.ini$'

Обычно настройки располагаются в каталоге /etc/php.d/. Имена файлов зависят от репозитория и способа установки PHP.

Не добавляйте строки zend_extension=opcache или extension=apcu повторно, если установленные RPM-пакеты уже создали соответствующие INI-файлы.

Настройка OPcache

Откройте INI-файл OPcache. В установке из Remi это часто файл /etc/php.d/10-opcache.ini.

sudo mcedit /etc/php.d/10-opcache.ini

Базовая конфигурация для обычного production-сервера:

; Включить OPcache для веб-запросов
opcache.enable=1

; Для обычных CLI-команд кеш чаще всего не нужен
opcache.enable_cli=0

; Общий объём памяти для скомпилированного PHP-кода
opcache.memory_consumption=256

; Память для повторяющихся строк, имён классов и методов
opcache.interned_strings_buffer=32

; Максимальное количество PHP-файлов в кеше
opcache.max_accelerated_files=32531

; Проверять изменения PHP-файлов
opcache.validate_timestamps=1

; Интервал проверки изменений в секундах
opcache.revalidate_freq=2

; Сохранять PHPDoc-комментарии для атрибутов, аннотаций и библиотек
opcache.save_comments=1

; JIT обычно не ускоряет типичные CMS и веб-приложения
opcache.jit=disable

Значения 256 МБ и 32531 — безопасная стартовая конфигурация для сервера с несколькими PHP-проектами. Для маленького сайта часто достаточно стандартных значений.

Режим с неизменяемыми релизами

Если приложение выкладывается отдельными релизами и PHP-файлы не редактируются прямо на сервере, проверку времени изменения можно отключить:

opcache.validate_timestamps=0

В таком режиме после каждого обновления кода необходимо перезапускать PHP-FPM:

sudo systemctl restart php-fpm

Не отключайте opcache.validate_timestamps, если файлы загружаются по SFTP, редактируются вручную или обновляются без управляемого процесса деплоя. Иначе PHP может продолжить выполнять старую версию кода.

Настройка APCu

Откройте INI-файл APCu. В зависимости от пакета он может называться 40-apcu.ini или иначе.

sudo mcedit /etc/php.d/40-apcu.ini

Стартовая конфигурация:

; Включить APCu
apc.enabled=1

; Память для пользовательских данных
apc.shm_size=64M

; Записи без собственного TTL не удаляются только по возрасту
apc.ttl=0

; Время хранения удалённых записей в списке сборки мусора
apc.gc_ttl=3600

; Не создавать отдельный кеш при каждом запуске CLI-команды
apc.enable_cli=0

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

Для большинства сайтов достаточно начать с 64M. Увеличивать значение следует по результатам наблюдения за заполнением кеша, а не заранее.

Проверка конфигурации и перезапуск

Проверим конфигурацию PHP-FPM перед перезапуском:

sudo php-fpm -t

Если ошибок нет, перезапускаем PHP-FPM:

sudo systemctl restart php-fpm
sudo systemctl status php-fpm --no-pager

Если сервис называется иначе, найдём его:

systemctl list-unit-files --type=service | grep -E '^php.*fpm\.service'

При использовании Apache с модулем mod_php вместо PHP-FPM потребуется перезапуск Apache:

sudo systemctl restart httpd

Проверка загруженных расширений

php -m | grep -Ei 'Zend OPcache|apcu'

php --ri 'Zend OPcache'
php --ri apcu

Команда php проверяет CLI-конфигурацию. PHP-FPM может использовать другой набор INI-файлов, поэтому дополнительно проверим его настройки:

php-fpm -i | grep -E 'opcache.enable|opcache.memory_consumption|apc.enabled|apc.shm_size'

Пример использования APCu

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

<?php

declare(strict_types=1);

function loadSettings(PDO $pdo): array
{
	$sql = '
		SELECT
			`name`,
			`value`
		FROM `AppSetting`
		WHERE `isActive` = 1
	';

	$statement = $pdo->query($sql);
	$rows = $statement->fetchAll(PDO::FETCH_ASSOC);

	$settings = [];

	foreach ($rows as $row)
	{
		$name = (string)($row['name'] ?? '');

		if ($name === '')
		{
			continue;
		}

		$settings[$name] = (string)($row['value'] ?? '');
	}

	return $settings;
}

function getSettings(PDO $pdo): array
{
	$apcuAvailable =
		function_exists('apcu_enabled')
		&& function_exists('apcu_fetch')
		&& function_exists('apcu_store')
		&& apcu_enabled();

	if (!$apcuAvailable)
	{
		return loadSettings($pdo);
	}

	$cacheKey = 'myapp:production:settings:v1';
	$settings = apcu_fetch($cacheKey, $cacheHit);

	if ($cacheHit && is_array($settings))
	{
		return $settings;
	}

	$settings = loadSettings($pdo);

	apcu_store(
		$cacheKey,
		$settings,
		300
	);

	return $settings;
}

После изменения настроек кеш можно удалить:

<?php

$cacheKey = 'myapp:production:settings:v1';

if (function_exists('apcu_delete'))
{
	apcu_delete($cacheKey);
}

При проверке результата apcu_fetch() нужно использовать второй параметр $cacheHit. Само закешированное значение может быть равно false, поэтому проверка вида $value !== false ненадёжна.

Краевые случаи

  • APCu очищается при перезапуске PHP-FPM. Приложение должно корректно работать и с пустым кешем.
  • APCu не синхронизируется между несколькими VPS, контейнерами или узлами балансировщика.
  • CLI и PHP-FPM используют разные процессы. При apc.enable_cli=0 кеш недоступен из консольного PHP.
  • При одновременном истечении популярного ключа несколько PHP-FPM-процессов могут одновременно пересчитать значение.
  • apcu_entry() предотвращает одновременное создание одного ключа, но callback выполняется под блокировкой. Внутри него не следует выполнять медленные HTTP-запросы и тяжёлые операции.
  • При opcache.validate_timestamps=0 изменения PHP-файлов не применятся без сброса OPcache или перезапуска PHP-FPM.
  • Конфигурация CLI может отличаться от конфигурации PHP-FPM, даже если используется одна версия PHP.

Безопасность

  • Не используйте APCu как защищённое хранилище паролей, API-ключей и других долгоживущих секретов.
  • Добавляйте к ключам название приложения, окружение и версию: myapp:production:settings:v1.
  • Не публикуйте без авторизации страницы со статистикой OPcache или APCu.
  • Не вызывайте apcu_clear_cache() из публичного обработчика пользовательского запроса.
  • При размещении нескольких независимых проектов изолируйте их отдельными PHP-FPM-пулами и системными пользователями.

Производительность

Признаки недостаточного размера OPcache:

  • кеш постоянно перезапускается;
  • заканчивается свободная память;
  • число PHP-файлов приближается к opcache.max_accelerated_files;
  • часть файлов не попадает в кеш.

Признаки недостаточного размера APCu:

  • частые очистки кеша;
  • большое число вытеснений записей;
  • низкая доля попаданий в кеш;
  • частое повторное выполнение дорогих запросов.

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

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

Совместимость

  • OPcache входит в стандартную поставку современных версий PHP.
  • APCu устанавливается как отдельное PECL-расширение или пакет операционной системы.
  • Пример конфигурации рассчитан на PHP 8.x и PHP-FPM.
  • Команды установки подходят для AlmaLinux, Rocky Linux и других RHEL-совместимых систем при использовании стандартных имён пакетов Remi.
  • При параллельной установке нескольких версий PHP имена пакетов, бинарных файлов и systemd-сервисов могут содержать номер версии.

Проверка через PHP-FPM

Для окончательной проверки можно временно создать PHP-файл в тестовом виртуальном хосте:

<?php

declare(strict_types=1);

header('Content-Type: application/json; charset=utf-8');

$opcacheStatus = function_exists('opcache_get_status')
	? opcache_get_status(false)
	: false;

$result = [
	'phpVersion' => PHP_VERSION,
	'sapi' => PHP_SAPI,
	'opcacheEnabled' => is_array($opcacheStatus),
	'apcuEnabled' => function_exists('apcu_enabled') && apcu_enabled(),
];

echo json_encode(
	$result,
	JSON_PRETTY_PRINT
	| JSON_UNESCAPED_UNICODE
	| JSON_THROW_ON_ERROR
);

Ожидаемый результат:

{
	"phpVersion": "8.x.x",
	"sapi": "fpm-fcgi",
	"opcacheEnabled": true,
	"apcuEnabled": true
}

После проверки удалите тестовый файл. Не оставляйте диагностические страницы в публичном доступе.

Альтернативы

  • Redis — когда кеш должен быть общим для нескольких серверов, контейнеров или фоновых обработчиков.
  • Memcached — простой распределённый кеш без сложных структур данных.
  • Файловый кеш — вариант для обычного хостинга без APCu, Redis и Memcached.
  • Кеш фреймворка или CMS — предпочтителен, если система уже предоставляет единый интерфейс и автоматическую инвалидацию.

Официальная документация

up: Просмотров: 2.3k
Материал помог? Оценка помогает находить устаревшие и спорные решения.

Комментарии

0

Нашли ошибку или хотите дополнить материал?

Комментариев пока нет.Можно первым дополнить материал или сообщить об ошибке.
Telegram