در وردپرس، Object Cache لایه‌ای است که نتایج کوئری‌ها و محاسبات سنگین را در حافظه ذخیره می‌کند و برای فروشگاه‌های پربازدید، تفاوت بین سرعت قابل قبول و کندی آزاردهنده را می‌سازد. بدون Backend خارجی مثل Redis یا Memcached، Object Cache فقط در هر درخواست زنده است و در پایان ریکوئست از بین می‌رود و همین موضوع، مزیت اصلی آن را از بین می‌برد. تفاوت Page Cache و Object Cache در سطح ذخیره‌سازی، تصمیم‌های معماری را به تصمیم‌های عملکردی گره می‌زند و انتخاب اشتباه هر لایه، هزینه پنهان ایجاد می‌کند. پیکربندی درست Redis، مدیریت Eviction Policy و پایش Hit Rate، سه لایه ضروری برای مقیاس‌پذیری هستند و نادیده گرفتن هر کدام، هزینه نگهداشت را چند برابر می‌کند. تست Object Cache در سه سطح ذخیره‌سازی، سرعت و پایداری انجام می‌شود و بدون آن، انتشار به تولید ریسک بالایی دارد. در این راهنما از اصول پایه تا استقرار تولیدی Object Cache را با نگاه مهندسی و کد عملی پوشش می‌دهیم.

در پروژه‌های واقعی، وقتی فروشگاهی با ترافیک بالا به من می‌رسد، اولین کارم فعال‌سازی Redis است. تفاوت قبل و بعد، معمولاً در حد چند ثانیه در زمان پاسخ سرور است. این راهنما از همان نقطه‌ای شروع می‌کند که تجربه می‌گوید بیشترین ارزش را دارد.

Object Cache چیست و چه تفاوتی با Page Cache دارد؟

Object Cache یک لایه ذخیره‌سازی در حافظه است که نتایج کوئری‌های دیتابیس و محاسبات سنگین را نگه می‌دارد. هدف آن، جلوگیری از اجرای مکرر همان کوئری است.

Page Cache لایه بالاتری است که کل HTML صفحه را ذخیره می‌کند. Object Cache لایه پایین‌تری است که داده خام را ذخیره می‌کند. این دو، مکمل یکدیگر هستند و نه جایگزین.

پیش از ادامه، راهنمای Transient vs Option و انتخاب صحیح را مطالعه کنید. اگر با ساختار کش در وردپرس آشنایی ندارید، راهنمای Object Cache در وردپرس نقطه شروع مناسبی است.

نشانه‌هایی که Object Cache ضروری است

اگر زمان پاسخ سرور بیش از ۵۰۰ms است، اگر تعداد کوئری‌های صفحه از ۱۰۰ عبور کرده، یا اگر تعداد کاربران همزمان زیاد است، به سراغ Object Cache بروید.

آناتومی Object Cache در وردپرس

وردپرس از API استانداردی برای Object Cache پشتیبانی می‌کند که شامل توابع زیر است:

wp_cache_get( $key, $group = '' );
wp_cache_set( $key, $data, $group = '', $expire = 0 );
wp_cache_delete( $key, $group = '' );
wp_cache_add( $key, $data, $group = '', $expire = 0 );
wp_cache_incr( $key, $offset = 1, $group = '' );
wp_cache_decr( $key, $offset = 1, $group = '' );
wp_cache_flush();

هر کلید در یک $group قرار می‌گیرد که امکان سازمان‌دهی و پاک‌سازی گروهی را فراهم می‌کند.

Non-Persistent و Persistent Cache

در نبود Backend خارجی، Object Cache فقط در طول یک ریکوئست زنده است و پس از آن از بین می‌رود. با Redis یا Memcached، Cache بین ریکوئست‌ها باقی می‌ماند.

// بررسی وجود Persistent Cache
if ( wp_using_ext_object_cache() ) {
    error_log( "Persistent Object Cache فعال است" );
} else {
    error_log( "Cache فقط در طول ریکوئست فعال است" );
}

انتخاب Backend: Redis یا Memcached

دو Backend اصلی برای Object Cache در وردپرس وجود دارد: Redis و Memcached.

معیارRedisMemcached
ساختار دادهپیشرفته (List، Set، Sorted Set)فقط Key/Value
Persistenceداردندارد
Replicationداردندارد
مصرف حافظهبالاترکمتر
محبوبیتبالامتوسط

برای فروشگاه‌های پربازدید، Redis انتخاب اول است. برای سایت‌های کوچک‌تر، Memcached کافی است.

انتخاب بر اساس سناریو

  1. Redis: فروشگاه، سایت عضویت‌محور، اپلیکیشن با داده ساختاریافته.
  2. Memcached: سایت خبری، وبلاگ پربازدید، سایت با کش ساده.

راه‌اندازی Redis برای وردپرس

راه‌اندازی Redis در سه مرحله انجام می‌شود: نصب سرور، نصب PHP Extension و نصب object-cache.php.

# نصب Redis سرور
sudo apt install redis-server

# بررسی وضعیت
redis-cli ping
# پاسخ: PONG

# نصب PHP Extension
sudo apt install php-redis
sudo systemctl restart php8.2-fpm

پیکربندی Redis

# در wp-config.php
define( "WP_REDIS_HOST", "127.0.0.1" );
define( "WP_REDIS_PORT", 6379 );
define( "WP_REDIS_DATABASE", 0 );
define( "WP_REDIS_TIMEOUT", 1 );
define( "WP_REDIS_READ_TIMEOUT", 1 );
define( "WP_REDIS_MAXTTL", 86400 );

پیکربندی Redis برای Multisite

define( "WP_CACHE_KEY_SALT", "wpk_" );
define( "WP_REDIS_PREFIX", "wpk_" );

فایل object-cache.php و نقش آن

برای فعال‌سازی Object Cache Persistent، باید فایل object-cache.php در پوشه wp-content قرار گیرد. این فایل، توابع wp_cache_* را با نسخه‌ای که به Redis یا Memcached متصل می‌شود، جایگزین می‌کند.

wp-content/
├── object-cache.php    ← فایل Drop-in
├── plugins/
└── themes/

توصیه می‌کنم از Plugin رسمی Redis Object Cache استفاده کنید که این فایل را به‌صورت حرفه‌ای مدیریت می‌کند.

بررسی فعال بودن Drop-in

if ( file_exists( WP_CONTENT_DIR . "/object-cache.php" ) ) {
    error_log( "Object Cache Drop-in فعال است" );
}

Eviction Policy و مدیریت حافظه

Redis دارای محدودیت حافظه است. تعیین Eviction Policy صحیح، از Crash سرور جلوگیری می‌کند.

# در /etc/redis/redis.conf
maxmemory 512mb
maxmemory-policy allkeys-lru

سه Policy رایج:

  1. allkeys-lru: قدیمی‌ترین کلیدها را حذف می‌کند.
  2. volatile-lru: فقط کلیدهای دارای TTL را حذف می‌کند.
  3. noeviction: هیچ کلیدی را حذف نمی‌کند و در صورت پر شدن، خطا برمی‌گرداند.

برای Object Cache وردپرس، allkeys-lru انتخاب پیشنهادی است.

محاسبه حجم حافظه موردنیاز

# در Redis CLI
INFO memory
# خروجی شامل used_memory_human است

قاعده کلی: ۱۰ تا ۱۵ درصد حجم دیتابیس، حافظه Redis کافی است.

Invalidation و پاک‌سازی هوشمند

پاک‌سازی Cache در زمان تغییر داده، حساس‌ترین بخش Object Cache است. اگر داده تغییر کند و Cache پاک نشود، کاربران داده قدیمی می‌بینند.

<?php
add_action( "save_post", function( $post_id ) {
    wp_cache_delete( "post_" . $post_id, "posts" );
    wp_cache_delete( "recent_posts", "posts" );
}, 10, 1 );

پاک‌سازی گروهی

// پاک کردن همه کلیدهای یک گروه
wp_cache_delete( "wpk_products", "wpk" );

// یا پاک‌سازی کل کش (با احتیاط)
wp_cache_flush();

wp_cache_flush() کل کش را پاک می‌کند و در سایت پربازدید، بار سنگینی ایجاد می‌کند. توصیه می‌کنم فقط برای موارد اضطراری استفاده شود.

Object Cache در WooCommerce

WooCommerce از Object Cache به‌طور گسترده استفاده می‌کند. جداول اصلی مثل wp_wc_product_meta_lookup و wp_wc_order_stats نتایج را کش می‌کنند.

// پاک کردن کش محصول در زمان ذخیره
add_action( "woocommerce_update_product", function( $product_id ) {
    wp_cache_delete( "product_" . $product_id, "products" );
    wp_cache_delete( "wc_product_" . $product_id, "woocommerce" );
} );

راهنمای ساخت افزونه ووکامرس حرفه‌ای نقطه شروع مناسبی است.

کش سبد خرید و Checkout

سبد خرید و Checkout نباید کش شوند. راهنمای کش صفحات فروشگاه بدون کش سبد را ببینید.

پایش Hit Rate و عملکرد

Hit Rate نرخ موفقیت کش است. اگر Hit Rate پایین باشد، یعنی Cache مفید نیست.

# در Redis CLI
INFO stats
# keyspace_hits و keyspace_misses

محاسبه Hit Rate: hits / (hits + misses) * 100. مقدار مطلوب بالای ۸۰ درصد است.

پایش با Plugin

Pluginهایی مثل Redis Object Cache و Query Monitor آمار Hit Rate را نمایش می‌دهند. راهنمای Query Monitor برای دیباگ وردپرس نقطه شروع مناسبی است.

تست و دیباگ

تست Object Cache در سه سطح انجام می‌شود: سطح ذخیره‌سازی، سطح سرعت و سطح پایداری.

<?php
add_action( "wp_footer", function() {
    if ( defined( "WP_DEBUG" ) && WP_DEBUG && current_user_can( "manage_options" ) ) {
        global $wp_object_cache;
        echo "<!-- Cache Hits: " . $wp_object_cache->cache_hits . " -->";
        echo "<!-- Cache Misses: " . $wp_object_cache->cache_misses . " -->";
        echo "<!-- Total Queries: " . get_num_queries() . " -->";
    }
} );

اشتباهات رایج در تست

اشتباه اول، نبود تست با ترافیک بالا. اشتباه دوم، نبود تست با داده متغیر. اشتباه سوم، نبود تست Invalidation. اشتباه چهارم، نبود تست با چند سرور. اشتباه پنجم، نبود تست رفتار در زمان قطعی Redis.

پرسش‌های پرتکرار درباره Object Cache

آیا Object Cache جایگزین Page Cache است؟

خیر، مکمل یکدیگر هستند. Object Cache داده خام را کش می‌کند، Page Cache HTML نهایی.

آیا Redis برای سایت کوچک ضروری است؟

خیر، برای سایت‌های کوچک Page Cache کافی است.

آیا Memcached می‌تواند جایگزین Redis شود؟

بله، برای کش ساده. اما Redis امکانات بیشتری دارد.

چرا Hit Rate من پایین است؟

احتمالاً TTL کوتاه است، Invalidation بیش از حد اجرا می‌شود، یا کلیدهای متغیر تولید می‌شوند.

آیا Object Cache با چند سرور کار می‌کند؟

بله، با Redis Cluster یا Memcached Cluster. راهنمای Redis Cluster را ببینید.

آیا Object Cache روی مصرف CPU اثر دارد؟

بله، Redis از CPU استفاده می‌کند اما در مقایسه با کوئری دیتابیس، بسیار کارآمدتر است.

نتیجه و مسیر ادامه

Object Cache لایه اصلی بهینه‌سازی عملکرد در وردپرس است. کلید موفقیت، انتخاب Backend مناسب، پیکربندی حرفه‌ای Redis، مدیریت Eviction Policy، Invalidation هوشمند و پایش مداوم است. اگر این لایه‌ها با دقت طراحی شوند، فروشگاه در طول سال‌ها سریع و مقیاس‌پذیر باقی می‌ماند.

پیشنهاد می‌کنم مسیر یادگیری را با Transient vs Option و انتخاب صحیح ادامه دهید و سپس Heartbeat API و کاهش بار سرور را به‌عنوان مکمل مطالعه کنید. همچنین مفهوم Redis را در ویکی‌پدیا مرور کنید.

اگر روی پروژه واقعی خود Object Cache را فعال کرده‌اید، برایم جالب است بدانید کدام بخش — Eviction Policy یا Invalidation — بیشترین چالش را ایجاد کرده است. تجربه خودتان را در دیدگاه‌ها بنویسید.