Redis Object Cache v5.7.40-v2: Drop-in Enterprise yang Akhirnya Menutup Semua Celah Cache Pollution

Jika kamu pernah mengelola WooCommerce high-traffic dengan Redis, kamu pasti pernah bertemu bug yang paling sulit di-debug: data produk tiba-tiba berubah sendiri dalam satu request, tanpa query baru, tanpa save_post. Penyebabnya bukan Redis, melainkan L1 cache in-memory di PHP.

v5.7.40-v2 lahir untuk menyelesaikan masalah itu secara arsitektural, bukan dengan tambalan.

Masalah Klasik: L1 vs L2 Tidak Koheren

Arsitektur object cache modern selalu punya 2 layer:

L1 = Local Array di PHP-FPM (super cepat, <1µs)
L2 = Redis (persisten antar request, ∼0.3ms)

Redis mengisolasi data secara natural lewat serialize() dan unserialize(). Data yang kamu SET adalah snapshot, data yang kamu GET adalah copy baru.

L1 tidak. L1 menyimpan reference asli. Inilah sumber cache pollution:

$post = wp_cache_get(123, 'posts'); // dari L1$post->post_title = 'Judul Promo'; // untuk ditampilkan saja
// ... 50 baris kemudian di request yang sama$post_again = wp_cache_get(123, 'posts'); // $post_again->post_title ikut jadi 'Judul Promo' — cache rusak

80% plugin populer — WooCommerce, Elementor, ACF — melakukan mutasi seperti ini. Di cache non-persisten WordPress itu memang diperbolehkan, tapi di persistent cache ini jadi bom waktu.

Filosofi v5.7.40-v2: L1 Harus Meniru Batas Serialisasi L2

Solusinya sederhana dan elegan: Jika L2 mengisolasi dengan serialize, maka L1 harus mengisolasi dengan clone.

v2 menerapkan ini di dua titik kritis dengan biaya hampir nol.

1. Clone-on-Write di set_local() — Isolasi Saat Tulis

Setiap data yang masuk ke L1 di-clone dulu.

// sebelum disimpan ke $this->localif (is_object($val)) $val = clone $val;

Hasilnya, L1 menyimpan snapshot independen, persis seperti Redis. Jika caller memodifikasi variabel asli setelah wp_cache_set(), L1 tidak ikut rusak. Ini adalah standar emas untuk cache coherence.

2. Fast-Path Deep Clone di return_value() — Isolasi Saat Baca

Ini yang paling jenius di v2. Fungsi get() dan get_multiple() tidak lagi return $val langsung.

private function return_value($v){    if (is_object($v)) return clone $v;    if (is_array($v)) {        // fast-path: cek dulu, jika array murni scalar → return as-is, zero cost        // jika array berisi object (misal get_posts() => [WP_Post, WP_Post])        // → clone setiap object di dalamnya    }    return $v;}

Dampaknya:

  • Array scalar murni seperti alloptions (200-500 key) → zero allocation, langsung return. Ini yang membuat overhead tetap <1%.
  • Array berisi object seperti hasil WP_Query → setiap WP_Post di-clone, array-nya sendiri di-copy. Bug get_posts() tertutup total.
  • Biaya real: clone 1 object ∼0.5-2µs, array 20 post ∼8-15µs. Jauh lebih murah dari 1 query database atau 1 RTT ke Redis.

Fitur Enterprise Lain yang Sudah Matang Sejak v5.7.28 – v5.7.39

v2 tidak hanya soal clone. Fondasinya sudah enterprise-grade:

a. 100% Atomic dengan Lua
BUMP_COUNTER_LUADECR_CLAMP_LUA, dan MIGRATE_COUNTER_LUA menggantikan pola GET + SET yang rawan race condition. flush_group() dan incr()/decr() sekarang atomic, preserve TTL, dan aman di 50 FPM worker bersamaan.

b. Resilience Saat Redis Down
Mode fail-open yang terkontrol. Saat Redis mati, L1 tetap melayani, write dianggap sukses secara lokal, dan semua bump versi antri di pending_ns_bumps. Saat Redis pulih, antrian di-replay otomatis. Tidak ada fatal error, tidak ada white screen.

c. Chunking untuk Skala Besar
MGETPIPELINE SET, dan UNLINK dipecah per 1000 key. Ini mencegah max bulk response error dan menjaga latency tetap stabil saat get_multiple() 10.000 key.

d. L1 Hygiene Cerdas
Limit 70.000 entry (∼30-50MB per worker) dengan eviction batch 2%. Saat flush_group('options') atau saat L1 >50%, prefix lama dibersihkan dari memory untuk mencegah bocor di long-running FPM.

e. SERIALIZER_NONE
Migrasi dari SERIALIZER_PHP ke manual serialize() memberikan kontrol penuh atas FALSE_TOKENnull (N;), dan integer murni dari INCRBY. Tidak ada lagi double-unserialize dan aman dari perubahan serializer di ext-redis.

Kompatibilitas

  • PHP 8.1+, WordPress 6.0+
  • Kompatibel dengan multisite, WP_REDIS_HOST unix socket, persistent connection, dan AOC_WOO_SKIP strict mode untuk wc_session dan customer_session
  • Tidak perlu konfigurasi. Drop-in ke wp-content/object-cache.php, satu kali wp cache flush.

Verdict

v5.7.40-v2 bukan sekadar optimasi performa. Ini adalah perbaikan arsitektural yang membuat L1 dan L2 100% koheren.

  • Scalar dan array murni berjalan secepat native PHP
  • Object dan array of objects terisolasi sempurna
  • Menutup semua vektor cache pollution yang selama ini membuat bug WooCommerce dan Elementor sulit dilacak

Jika v5.7.39 adalah yang paling cepat, maka v5.7.40-v2 adalah yang paling benar.

Tinggalkan Balasan