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 — предпочтителен, если система уже предоставляет единый интерфейс и автоматическую инвалидацию.
Комментарии
0Нашли ошибку или хотите дополнить материал?