Redis Object Cache – Stripped (v5.4.8)
🎯 Mengapa Plugin Ini Dibuat?
object-cache.php yang saya kembangkan sebagai respons terhadap kebutuhan:- ✅ Zero-dependency: Hanya butuh ekstensi
php-redis, tanpa library eksternal - ✅ Ultra-clean L1/L2 coherence: Local cache (L1) dan Redis (L2) selalu sinkron tanpa race condition
- ✅ Fail-open yang aman: Tetap berfungsi saat Redis down tanpa corrupt data
- ✅ JIT micro-optimized: Eviction L1, key hashing, dan pipeline batching yang efisien
- ✅ Production-hardened: 12 koreksi kritis di v5.4.8 untuk edge case real-world
🏗️ Arsitektur: Hybrid L1/L2 dengan Key Versioning
┌─────────────────────────────────────┐
│ WordPress Request │
└─────────┬───────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ L1: Local Cache (PHP Array) │
│ • O(1) lookup │
│ • Max 100k entries (configurable) │
│ • Auto-eviction LRU-style │
└─────────┬───────────────────────────┘
│ Miss / Force Refresh
▼
┌─────────────────────────────────────┐
│ L2: Redis Backend │
│ • Persistent storage │
│ • Key versioning untuk invalidation│
│ • Pipeline batching untuk bulk ops │
└─────────────────────────────────────┘
🔑 Strategi Key Versioning (Tanpa SCAN/KEYS!)
SCAN atau KEYS yang berbahaya di production, plugin ini mengimplementasikan namespace versioning:// Format key persistent:
// {SALT}:{NS}:{BLOG_PREFIX}:{GROUP}:v{GV}:{KEY}
// Contoh:
// aoc123:42:1:options:v1735689200:alloptions
- NS (Namespace Version): Di-increment saat
flush()global → invalidate seluruh cache - GV (Group Version): Di-increment per-group saat
flush_group()→ invalidate spesifik group - Runtime caching:
$gv_runtimemenyimpan GV di memory agar tidak perlu query Redis berulang
⚡ Fitur Utama & Optimasi
1. Local Cache (L1) dengan Eviction Cerdas
$slice_amount = max(1, (int) (AOC_LOCAL_CACHE_LIMIT * 0.25));
$this->local = array_slice($this->local, $slice_amount, null, true);
- Mencegah memory bloat di PHP-FPM worker
max(1, ...)memastikan tidak crash di limit kecil
2. Fail-Open yang Safe & Predictable
// Write operations tetap bisa ke L1 saat Redis down
if (!$this->redis_ok && $this->cfg_fail_open_write) {
$this->set_local($full, $val); // Fallback aman
return true;
}
- Konfigurasi via
AOC_FAIL_OPEN_WRITE - Tetap menghormati semantik
add()/replace()walau Redis down
3. Recovery Auto-Healing
private function check_redis_recovery(): void {
if (time() – self::$last_retry > $this->cfg_failover_ttl) {
$this->init_redis(); // Coba reconnect
if ($this->redis_ok) {
$this->gv_runtime = []; // Reset state agar koheren
}
}
}
- Retry setiap 15 detik (default)
- Reset
$gv_runtimesaat recovery → mencegah stale version
4. WooCommerce Compatibility Mode
if (AOC_WOO_SKIP && $this->woo_strict) {
$this->np_groups[“term-queries”] = true; // Skip cache untuk query tertentu
}
- Mode
strict: otomatis bypass cache untuk key yang rentan race condition di Woo - Konfigurasi via
AOC_WOO_MODE: "strict" | "relaxed"
5. Batch Operations dengan Pipeline
// get_multiple / set_multiple / delete_multiple
foreach (array_chunk($keys, $this->chunk_size) as $chunk) {
$this->redis->multi(Redis::PIPELINE);
// … queue operations
$this->redis->exec(); // Single round-trip
}
- Chunk size configurable via
AOC_BATCH_CHUNK(default: 1000) - Mengurangi network overhead hingga 90% untuk bulk operations
⚙️ Konfigurasi (wp-config.php)
define(‘WP_CACHE_KEY_SALT’, ‘yourwebsitekeysalt::’);
define(‘WP_CACHE’, true);
// — Koneksi Redis —
define(‘WP_REDIS_HOST’, ‘127.0.0.1’);
define(‘WP_REDIS_PORT’, 6379);
define(‘WP_REDIS_DATABASE’, 0);
define(‘WP_REDIS_PASSWORD’, ”); // Opsional
// — Behavior Cache —
define(‘AOC_LOCAL_CACHE_LIMIT’, 100000); // Max entries di L1
define(‘AOC_FAIL_OPEN_WRITE’, false); // Izinkan write ke L1 saat Redis down
define(‘AOC_FAILOVER_TTL’, 15); // Retry interval (detik)
define(‘AOC_DEFAULT_NOEXP_TTL’, 2592000); // TTL default untuk key tanpa expire (30 hari)
define(‘AOC_KEY_TTL_MAX’, 2592000); // Max TTL yang diizinkan
define(‘AOC_MAX_KEY_LENGTH’, 230); // Batas panjang key sebelum di-hash
define(‘AOC_BATCH_CHUNK’, 1000); // Chunk size untuk pipeline
// — Multisite & WooCommerce —
define(‘AOC_NS_PER_BLOG’, true); // Namespace terpisah per blog di multisite
define(‘AOC_WOO_SKIP’, true); // Aktifkan bypass untuk Woo
define(‘AOC_WOO_MODE’, ‘strict’); // “strict” atau “relaxed”
// — Advanced —
define(‘AOC_REDIS_TIMEOUT’, 1.5); // Connection timeout (detik)
define(‘AOC_REDIS_PERSISTENT’, true); // Gunakan pconnect()
📦 Instalasi & Penggunaan
Langkah 1: Pastikan Prasyarat
# PHP 8.0+
php -v
# Ekstensi Redis terinstall
php -m | grep redis
# Redis server berjalan
redis-cli ping # Harus return: PONG
Langkah 2: Deploy Drop-in
# Copy file ke wp-content/
cp object-cache.php /path/to/wordpress/wp-content/
# Pastikan file bisa dibaca web server
chown www-data:www-data /path/to/wordpress/wp-content/object-cache.php
Langkah 3: Verifikasi
/wp-admin dan cek:- Tidak ada error PHP/Redis
- Object cache stats muncul di debug bar (jika pakai)
- Atau panggil manual:
wp_cache_supports('flush_group')→ harus returntrue
Debugging
// Aktifkan logging
define(‘WP_DEBUG’, true);
define(‘WP_DEBUG_LOG’, true);
// Cek status cache
if (isset($GLOBALS[‘wp_object_cache’])) {
echo $GLOBALS[‘wp_object_cache’]->stats();
}
🧪 Testing & Monitoring
Unit Test Edge Cases
// Test null value handling
wp_cache_set(‘test_null’, null, ‘default’);
$found = null;
$val = wp_cache_get(‘test_null’, ‘default’, false, $found);
assert($val === null && $found === true);
// Test group versioning coherence
wp_cache_flush_group(‘options’);
// Key lama di group ‘options’ harus miss, group lain tetap hit
Monitoring di Production
# Redis memory & keys
redis-cli INFO memory
redis-cli DBSIZE
# PHP-FPM memory usage
pm.status_path = /status
curl localhost/status?full
# Log AOC
tail -f /path/to/wp-content/debug.log | grep “\[AOC Redis\]”
🤔 FAQ
A: Tidak. Ini adalah drop-in replacement. Hanya satu
object-cache.php yang aktif.A: Semua key memiliki TTL (default 30 hari untuk no-expire). Tidak ada key abadi → aman dari memory leak.
A: Tidak secara native. Plugin ini dirancang untuk single-node Redis dengan koneksi stabil. Untuk cluster, pertimbangkan proxy seperti Twemproxy di depan.
A: Di high-traffic multisite, hybrid L1/L2 ini lebih scalable:
- L1: ~0.002ms/lookup
- L2 (Redis local): ~0.3ms/lookup
- L2 (Redis remote): ~1-3ms/lookup
Dengan hit ratio 95%+, rata-rata latency < 0.15ms.
🚀 Kesimpulan
- 🎯 Predictability: Behavior konsisten di semua kondisi (Redis up/down, high/low load)
- 🔐 Correctness: Koherensi data dijamin lewat versioning + runtime state management
- ⚡ Efficiency: Minimal overhead, maksimal throughput
📥 Download: Whatsapp saya untuk mencoba file drop-in object-cache ini.


