APCu (APC User Cache) 是 PHP 共享內存緩存擴展,提供鍵值存儲、 opcode 緩存(已分離)、高性能讀寫。本文涵蓋安裝、管理界面、核心 API、進階用法、性能調優與遷移建議。
sudo apt-get install php-apcu
# PHP 7.0+ 專用包:php7.4-apcu, php8.1-apcu 等
php_apcu.dllext/ 目錄php.ini 添加:extension=apcuapc.enabled=1
apc.shm_size=128M # 共享內存大小
apc.ttl=3600 # 默認 TTL (秒),0=永不過期
apc.gc_ttl=3600 # 垃圾回收 TTL
apc.entries_hint=4096 # 預估條目數,優化哈希表
apc.mmap_file_mask=/tmp/apc.XXXXXX # mmap 文件掩碼
重啟 Web 服務器生效。
/usr/share/php/apcu.php 或 PEAR 安裝路徑defaults('ADMIN_USERNAME','admin'); defaults('ADMIN_PASSWORD','strong_pass');<?php
// 設置 (僅不存在時成功)
apcu_add('key', 'value', 3600); // 返回 bool
// 設置/覆蓋
apcu_store('key', 'new_value', 7200); // 返回 bool
// 獲取
$value = apcu_fetch('key'); // 返回值或 false
$success = apcu_fetch('key', $success); // 引用參數區分 "值為 false" 與 "不存在"
// 刪除
apcu_delete('key'); // 返回 bool
// 批量獲取
$keys = ['a', 'b', 'c'];
$values = apcu_fetch($keys); // 返回 ['a'=>val, ...]
// 批量刪除
apcu_delete(['a', 'b', 'c']);
// 判斷存在
apcu_exists('key'); // 返回 bool
apcu_exists(['a', 'b']); // 返回 ['a'=>true, 'b'=>false]
apcu_store('counter', 10);
apcu_inc('counter'); // 11
apcu_inc('counter', 5); // 16
apcu_dec('counter', 3); // 13
// 返回新值,失敗返回 false
$old = 100;
$new = 200;
// 僅當當前值等於 $old 時設置為 $new
$success = apcu_cas('key', $old, $new); // 返回 bool
// 適用於計數器、狀態機、分布式鎖基礎
foreach (new APCUIterator() as $entry) {
echo "{$entry['key']} => {$entry['value']} (size: {$entry['size']}, hits: {$entry['hits']})\n";
}
// 正則過濾
foreach (new APCUIterator('/^user_\d+$/') as $entry) {
// ...
}
function getWithLock($key, $ttl, callable $loader) {
$value = apcu_fetch($key);
if ($value !== false) return $value;
// 獲取鎖 (CAS 自旋)
$lockKey = "lock:{$key}";
$lockTimeout = 10; // 秒
$start = time();
while (time() - $start < $lockTimeout) {
if (apcu_add($lockKey, 1, 5)) { // 5秒鎖過期
try {
$value = $loader();
apcu_store($key, $value, $ttl);
return $value;
} finally {
apcu_delete($lockKey);
}
}
usleep(10000); // 10ms
}
// 鎖超時,返回舊值或拋出異常
return apcu_fetch($key) ?: throw new Exception("Cache miss & lock timeout");
}
class TaggedCache {
private $prefix = 'tagged:';
public function set($key, $value, $tags = [], $ttl = 3600) {
apcu_store($this->prefix . $key, $value, $ttl);
foreach ($tags as $tag) {
$tagKey = $this->prefix . 'tag:' . $tag;
$keys = apcu_fetch($tagKey) ?: [];
$keys[$key] = true;
apcu_store($tagKey, $keys, $ttl);
}
}
public function invalidateTag($tag) {
$tagKey = $this->prefix . 'tag:' . $tag;
$keys = apcu_fetch($tagKey) ?: [];
foreach (array_keys($keys) as $key) {
apcu_delete($this->prefix . $key);
}
apcu_delete($tagKey);
}
}
| 維度 | APCu | Redis |
|---|---|---|
| 架構 | 本機共享內存 | 網絡服務/集群 |
| 性能 | 極高 (μs 級) | 高 (ms 級網絡開銷) |
| 持久化 | 無 (進程重啟丟失) | 支持 RDB/AOF |
| 多實例共享 | 不支持 (僅單機多進程) | 原生支持 |
| 數據結構 | 簡單 K-V | 豐富 (List/Set/Hash/Stream) |
| 適用場景 | 單機熱點數據、opcode 緩存輔助 | 分佈式緩存、會話、隊列、排行榜 |
apc_* 函數在 APCu 中大多保留,但建議遷移到 apcu_* 前綴APCu 是單機高性能緩存利器,合理搭配 Redis 構建多級緩存體系。