Object Cache در وردپرس مکانیزمی است که نتیجه پرس‌وجوها و اشیای پرتکرار را موقتا در حافظه نگه می‌دارد تا در همان درخواست یا بین درخواست‌ها دوباره از دیتابیس خوانده نشوند. Redis زمانی واقعا مفید است که این کش را «پایدار» و بیرون از PHP نگه دارید؛ مخصوصا در سایت‌های پویا با کاربر لاگین (مثل فروشگاه، عضویت، LMS)، ترافیک همزمان بالا، شبکه چندسایته و وقتی گلوگاه شما تعداد زیاد کوئری و تاخیر دیتابیس است. اگر بیشتر ترافیک شما مهمان و صفحات استاتیک با Page Cache تحویل می‌شود، معمولا نفع Redis کم است.

Object Cache دقیقا چیست؟

وردپرس یک API کش داخلی دارد (تابع‌های wp_cache_*). به صورت پیش‌فرض این کش «غیرپایدار» است؛ یعنی فقط در طول همان درخواست PHP معتبر است و با پایان درخواست از بین می‌رود. نتیجه: در یک صفحه اگر کدی چند بار همان کوئری را اجرا کند، پاسخ از کش داخلی می‌آید؛ اما درخواست بعدی دوباره به دیتابیس می‌رود.

وقتی «Persistent Object Cache» را فعال کنید، همین API به یک پشتوانه بیرونی مثل Redis یا Memcached متصل می‌شود و داده‌ها بین درخواست‌ها هم باقی می‌مانند. در این حالت بسیاری از پرس‌وجوهای تکراری بدون لمس دیتابیس پاسخ می‌گیرند.

Redis برای Object Cache چه می‌کند؟

Redis یک دیتابیس درون‌حافظه‌ای است که عملیات خواندن/نوشتن کلید-مقدار را با تاخیر بسیار کم انجام می‌دهد. با نصب افزونه مناسب، وردپرس کلیدهایی مثل نتایج WP_Query، ترنزینت‌ها و برخی محاسبات پرتکرار را در Redis می‌گذارد. هر کلید می‌تواند تاریخ انقضا (TTL) داشته باشد و با رخدادهایی مثل به‌روزرسانی پست، از کش بی‌اعتبار شود. نتیجه مستقیم، کاهش تعداد کوئری‌های MySQL و بهبود TTFB در مسیرهای پویا است.

تفاوت Object Cache با Page Cache

Page Cache (کش کامل صفحه) نسخه HTML آماده را تحویل می‌دهد و برای بازدیدکنندگان مهمان عالی است؛ اما برای کاربران لاگین یا صفحات شخصی‌سازی‌شده خیلی کم اثر است. Object Cache زیرساخت دیتابیس را سبک می‌کند و در هر دو حالت (لاگین و مهمان) موثر است، ولی HTML کامل تولید نمی‌کند. در عمل این دو مکمل هم هستند، نه جایگزین.

چه زمانی Redis واقعا مفید است؟

  • کاربران لاگین زیاد دارید: فروشگاه‌های ووکامرس، سایت‌های عضویت، LMS، داشبوردهای کاربری.
  • سایت چندسایته (Multisite) یا چندزبان با کوئری‌های پرتکرار.
  • ترافیک همزمان بالاست و بار اصلی روی دیتابیس می‌افتد.
  • بخش‌هایی از سایت قابل Page Cache نیست (سبد خرید، حساب کاربری، نتایج جستجوی داخلی، API/REST).
  • دیتابیس دور از اپلیکیشن است یا تاخیر شبکه/دیسک محسوس است.
  • ترنزینت‌های زیادی دارید؛ با کش پایدار، ترنزینت‌ها هم از Redis سرو می‌شوند.
  • کوئری‌های گران (JOIN، متا کوئری پیچیده) یا محاسبات پرتکرار دارید که همیشه لازم نیست از منبع محاسبه شوند.

چه زمانی Redis ارزش افزوده کمی دارد؟

  • سایت محتوایی کوچک که تقریبا همه صفحات با Page Cache و CDN کش می‌شوند.
  • ترافیک پایین یا کوئری‌های بسیار سبک؛ گلوگاه شما PHP/CPU است نه دیتابیس.
  • سرور RAM کافی ندارد یا هاست اشتراکی امکان اجرای Redis نمی‌دهد.
  • کد/افزونه‌ها کوئری‌های غیرضروری تولید می‌کنند؛ اول بهینه‌سازی را انجام دهید، بعد سراغ کش بروید.

چگونه تصمیم بگیریم؟ یک معیار عملی

قبل از نصب هر چیزی، وضعیت موجود را اندازه بگیرید. اگر پس از فعال‌سازی کش پایدار، شاخص‌های زیر به شکل معنادار بهتر شدند، Redis مناسب شماست:

شاخص‌هایی که باید بهتر شوند

  • کاهش محسوس تعداد کوئری‌های دیتابیس در صفحات پویا (با ابزارهایی مثل Query Monitor).
  • کاهش TTFB در صفحات لاگین‌دار و مسیرهای API.
  • پایداری بیشتر زمان پاسخ در ترافیک همزمان (نوسان کمتر).

روش گام‌به‌گام ارزیابی

  1. یک مسیر پویا را انتخاب کنید (مثل /my-account یا /cart).
  2. Baseline بگیرید: تعداد کوئری‌ها، TTFB و زمان تولید صفحه را ثبت کنید.
  3. Persistent Object Cache با Redis را فعال کنید.
  4. همان سناریو را تکرار و اعداد را مقایسه کنید.
  5. در بار همزمان متوسط (چند درخواست موازی) نیز مقایسه کنید.

راه‌اندازی ایمن و حداقلی Redis در وردپرس

  1. روی سرور Redis را نصب و سرویس را اجرا کنید یا از سرویس مدیریت‌شده استفاده کنید.
  2. افزونه‌ای که Object Cache را به Redis متصل می‌کند نصب کنید و Drop-in کش (فایل object-cache.php) را فعال کنید.
  3. تنظیمات حداقلی را در wp-config.php اضافه کنید.
<?php
// wp-config.php

// اگر Redis روی همان سرور است:
define('WP_REDIS_HOST', '127.0.0.1');
define('WP_REDIS_PORT', 6379);

// اگر رمز دارید:
// define('WP_REDIS_PASSWORD', 'strong-password');

// برای تفکیک کلیدها بین محیط‌ها/سایت‌ها:
define('WP_CACHE_KEY_SALT', 'example.com:');

// TTL پیش‌فرض برای کلیدهایی که شما ست می‌کنید (ثانیه):
// (اختیاری - به نیاز اپلیکیشن بستگی دارد)
define('WP_REDIS_MAXTTL', 3600);

نکته‌های ضروری:

  • برای هر محیط (dev/stage/prod) یک KEY_SALT متفاوت بگذارید تا کلیدها تداخل نکنند.
  • RAM را پایش کنید. اگر حافظه کم است، سیاست حذف کلید (eviction) باعث نوسان عملکرد می‌شود.
  • بعد از فعال‌سازی، سلامتی کش، نرخ Hit/Miss و کاهش کوئری را بررسی کنید.

نمونه کد: کش‌کردن نتیجه یک کوئری پرهزینه

هدف: نتایج یک پرس‌وجوی سنگین را 10 دقیقه کش کنیم تا در درخواست‌های بعدی بدون تماس با دیتابیس بازگردد.

<?php
/**
 * دریافت محصولات ویژه با کش شیء
 */
function codity_get_featured_products() {
    $cache_key   = 'featured_products_v1';
    $cache_group = 'products';
    $ttl         = 600; // 10 دقیقه

    // تلاش برای خواندن از کش
    $products = wp_cache_get( $cache_key, $cache_group );
    if ( false !== $products ) {
        return $products; // Hit
    }

    // کوئری پرهزینه (مثال)
    $query = new WP_Query( array(
        'post_type'      => 'product',
        'posts_per_page' => 12,
        'meta_query'     => array(
            array(
                'key'   => '_is_featured',
                'value' => 'yes',
            )
        )
    ) );

    $products = wp_list_pluck( $query->posts, 'ID' );

    // ذخیره در کش با TTL
    wp_cache_set( $cache_key, $products, $cache_group, $ttl );

    return $products;
}

چطور مطمئن شویم کار می‌کند؟ یک بار تابع را فراخوانی کنید، تعداد کوئری‌ها را یادداشت کنید. بار دوم در همان صفحه یا درخواست بعدی، باید کوئری‌ها کمتر شوند و فراخوانی از کش انجام شود. اگر داده با تغییر محتوا باید تازه شود، یا TTL را کوتاه‌تر کنید یا هنگام رویداد مربوط (مثلا ذخیره محصول) کلید مربوط را با wp_cache_delete حذف کنید.

محدودیت‌ها و خطاهای رایج

  • اشتباه گرفتن Object Cache با Page Cache: Redis HTML کامل تولید نمی‌کند؛ برای مهمان‌ها همچنان Page Cache/CDN لازم است.
  • عدم بی‌اعتبارسازی کلیدهای سفارشی: وردپرس کلیدهای هسته را مدیریت می‌کند؛ اما اگر خودتان کش می‌گذارید باید زمان انقضا بدهید یا کلید را در رویداد مناسب پاک کنید.
  • RAM ناکافی یا پیکربندی ناصحیح: کمبود حافظه باعث حذف کلیدهای داغ و نوسان عملکرد می‌شود.
  • نام‌گذاری مبهم گروه/کلید: از نام گروه مشخص (مثل products، users) و نسخه‌دهی کلید (featured_products_v1) استفاده کنید تا در تغییر ساختار داده، کلید قدیمی را کنار بگذارید.
  • Stampede (هجوم همزمان): برای کوئری‌های خیلی سنگین، از TTL‌های معقول و تکنیک‌هایی مثل قفل نرم (soft lock) استفاده کنید تا چند پردازه همزمان کش را بازسازی نکنند.
  • شیءهای خیلی بزرگ: آرایه‌های عظیم را در کش نگذارید؛ قطعه‌بندی یا داده حداقلی ذخیره کنید.
  • تاخیر شبکه: اگر Redis روی سرور دیگر است و شبکه کند است، سود کش ممکن است خنثی شود؛ نزدیکی فیزیکی اهمیت دارد.

Redis یا Memcached؟ کدام را انتخاب کنیم؟

هر دو سریع و درون‌حافظه‌ای‌اند. Redis معمولا امکانات بیشتری مثل انواع داده متنوع، مانیتورینگ و پایداری اختیاری (Persistence) ارائه می‌دهد و در اکوسیستم وردپرس پشتیبانی گسترده‌ای دارد. اگر همین حالا Memcached در زیرساخت شما پایدار و نزدیک به اپلیکیشن است، مهاجرت الزامی نیست؛ معیار واقعی، تاخیر، پایداری و سهولت نگهداری در محیط شماست.

سوالات متداول

آیا روی هاست اشتراکی می‌توانم Redis Object Cache را فعال کنم؟

فقط اگر هاست شما سرویس Redis یا جایگزین سازگار ارائه کند. در غیر این صورت، باید به سرور مجازی/اختصاصی یا سرویس مدیریت‌شده Redis مهاجرت کنید.

آیا Redis با ووکامرس تداخل دارد؟

به طور کلی خیر. در سایت‌های فروشگاهی، کش شیء می‌تواند بار دیتابیس را کاهش دهد. فقط برای کلیدهای سفارشی خودتان بی‌اعتبارسازی درست را رعایت کنید.

آیا با فعال کردن Redis دیگر به Page Cache نیاز ندارم؟

خیر. Page Cache برای بازدیدکنندگان مهمان همچنان بیشترین تاثیر را دارد. بهترین نتیجه وقتی به دست می‌آید که هر دو لایه به درستی تنظیم شوند.

نتیجه نهایی

اگر عمده ترافیک شما پویا و لاگین‌دار است یا دیتابیس گلوگاه شده، Persistent Object Cache با Redis می‌تواند تفاوت معنادار ایجاد کند. یک پایلوت کوچک با سناریوی واقعی اجرا کنید، شاخص‌ها را بسنجید و فقط در صورت بهبود پایدار، آن را به کل سایت تعمیم دهید. اگر سایت شما بیشتر استاتیک است، اولویت با Page Cache، CDN و بهینه‌سازی کوئری‌ها است.