In PHP development practice, APCu extensions are often used to share data between requests. However, because PHP's shared memory mechanism is limited by its running model (especially the multi-process mode of FPM or Apache), developers often misunderstand "multi-process shared cache". This article will explore how to implement the shared use of APCu cache in a typical multi-process program through the apcu_entry function.
APCu (Alternative PHP Cache User) is a user cache module of PHP, which implements data caching based on shared memory. It is suitable for CLI mode and Web mode, but has one limitation: under the multi-process model, variable space is not shared between each PHP process, and APCu sharing depends on memory mapping .
This means that as long as PHP uses the same APCu memory area, all processes can access cached data in this shared memory. Although variable scope is isolated, cache is not.
apcu_entry is a function introduced in PHP 5.5+ to obtain or generate cache items. Its typical usage is as follows:
$value = apcu_entry('cache_key', function() {
return some_expensive_function();
});
Its working principle is:
Check whether cache_key exists;
If it exists, return directly;
If it does not exist, execute the function in the closure, cache the result, and return it.
This "lazy computing + caching" strategy is very suitable for resource sharing requirements in multiple processes.
Taking PHP's pcntl_fork as an example, we simulate a multi-process scenario to verify whether the cache is shared:
<?php
if (!extension_loaded('apcu')) {
die("APCu Extension not enabled\n");
}
apcu_clear_cache();
$pid = pcntl_fork();
if ($pid == -1) {
die("Unable to create a child process\n");
} elseif ($pid === 0) {
// Subprocess
$data = apcu_entry('shared_key', function () {
echo "Subprocess:Cache miss,Generate data\n";
return 'Subprocess写入的数据 ' . time();
});
echo "Subprocess读取缓存:$data\n";
} else {
// Parent process
sleep(1); // 等待Subprocess先执行
$data = apcu_entry('shared_key', function () {
echo "Parent process:Cache miss,Generate data\n";
return 'Parent process写入的数据 ' . time();
});
echo "Parent process读取缓存:$data\n";
}
Usually you will see:
Subprocess:Cache miss,Generate data
Subprocess读取缓存:Subprocess写入的数据 1715600000
Parent process读取缓存:Subprocess写入的数据 1715600000
This shows that APCu's cached content is indeed shared between parent and child processes.
Make sure that PHP is using the same SAPI (for example, running multiple child processes in CLI mode) ;
Confirm that apc.enable_cli=1 is enabled in php.ini , otherwise APCu will not be enabled in CLI mode;
APCu is not suitable for multi-server cache sharing (such as multiple PHP instances under load balancing) . If you need multi-machine cache, please use Redis, Memcached and other services;
Avoid over-dependence on cache persistence , APCu is a process-level cache, and restarting PHP-FPM will cause data loss.
Suppose we get configuration data from the remote API:
$config = apcu_entry('remote_config', function () {
echo "Get data from remote interface...\n";
$json = file_get_contents('https://gitbox.net/api/config');
return json_decode($json, true);
});
As long as the cache has not expired, no process calls this logic and will repeatedly request the interface. This greatly improves performance and reduces the number of remote calls.
apcu_entry provides an elegant caching mechanism, especially suitable for scenarios where "high computational cost or high call cost". In a multi-process PHP program, the cached content of APCu can be shared among processes as long as the running environment allows. Understanding its operating principles and limitations will help you build high-performance PHP applications more efficiently.