آموزش نصب و تنظیم Redis برای کش وردپرس روی VPS
با نصب Redis روی VPS، پرسوجوهای دیتابیس را در حافظه کش کنید. این راهنما نحوه تنظیم maxmemory، انتخاب eviction policy و اتصال به localhost برای افزایش سرعت wp-admin را توضیح میدهد.
کش اشیاء Redis برای وردپرس چه کاری انجام میدهد
کش اشیاء Redis برای وردپرس، نتایج پرسوجوهای پایگاه داده را در حافظه ذخیره میکند تا درخواست بعدی بهجای پرسش مجدد از MySQL، آنها را از Redis بخواند. وردپرس در هسته خود یک کش اشیاء دارد، WP_Object_Cache، اما این کش در حافظه PHP قرار دارد و با پایان یافتن درخواست، پاک میشود. یک فایل drop-in، آن را با فایلی جایگزین میکند که با Redis در ارتباط است، بنابراین کش از یک درخواست تا درخواست بعدی باقی میماند.
کش اشیاء با کش صفحه متفاوت است و همین تفاوت تعیین میکند که آیا این راهنما برای شما مفید است یا خیر. کش صفحه، HTML نهایی یک URL را ذخیره میکند و آن را بدون اجرای PHP دوباره ارائه میدهد. این روش از هر کاری که Redis بتواند انجام دهد سریعتر است و برای بازدیدکنندگانی که وارد سیستم نشدهاند، کارایی دارد. به محض اینکه شخصی وارد سیستم شود، کالایی را به سبد خرید اضافه کند یا پنل مدیریت را باز کند، کش صفحه کنار میرود و وردپرس کل درخواست را اجرا میکند: bootstrap، افزونهها و پرسوجوها. کش اشیاء باعث میشود هزینه پردازشی آن درخواست کمتر شود. این ابزار برای ترافیکی است که کش صفحه نمیتواند پوشش دهد: نشستهای کاربران واردشده، سبد خرید، تسویه حساب و wp-admin. در یک فروشگاه WooCommerce، این بخش بیشترین ترافیک سنگین را تشکیل میدهد.
این دو در کنار هم قرار میگیرند و در یک سایت پربازدید، هر دو ضروری هستند. مشخص کنید که در حال حل چه مشکلی هستید. یک سایت معرفی که خوانندگان ناشناس دارد، تقریباً تمام سرعت خود را از کش صفحه میگیرد و افزودن Redis به آن تغییر چندانی ایجاد نمیکند.
یک محدودیت صادقانه پیش از شروع: کش اشیاء، یک پرسوجوی کند را سریع نمیکند. بلکه تکرار پرسوجویی که قبلاً اجرا شده است را حذف میکند. اولین درخواست پس از یک miss، هزینه کامل را میپردازد، بنابراین افزونهای که یک پرسوجوی بدون ایندکس را اجرا میکند، همچنان آن را یک بار در طول عمر کش اجرا خواهد کرد.
پیشنیازها
- یک سرور مجازی لینوکس با دسترسی shell و
sudo. نیازی به کنترل پنل نیست. - وردپرس که توسط PHP-FPM سرویسدهی میشود، برای مثال روی یک LAMP stack روی Ubuntu 24.04.
- ابزار WP-CLI روی سرور. تمام مراحل اینجا معادلهایی در پنل مدیریت دارند، اما نسخه shell سریعتر است.
- Redis روی همان ماشینی که PHP قرار دارد. هدف اصلی کاهش تأخیر (latency) است و وجود یک hop شبکه، این مزیت را از بین میبرد.
دستورات زیر برای Ubuntu 24.04 با PHP 8.3 و کاربر وب www-data نوشته شدهاند. نسخه PHP و نام کاربر را متناسب با سرور خود تغییر دهید. دستورات wp را از داخل دایرکتوری وردپرس، یعنی همانجایی که wp-config.php قرار دارد، اجرا کنید.
نصب Redis و افزونه PHP
sudo apt update
sudo apt install -y redis-server php-redis
sudo systemctl enable --now redis-server
redis-cli pingredis-cli ping باید پاسخ PONG را برگرداند. اگر خروجی Could not connect to Redis at 127.0.0.1:6379: Connection refused باشد، یعنی سرور در حال اجرا نیست؛ بنابراین پیش از ادامه، systemctl status redis-server را مطالعه کنید.
php-redis همان PhpRedis است، افزونه C که از طریق PECL ارائه میشود. این افزونه از Predis که کاملاً با PHP نوشته شده سریعتر است و پلاگین در صورت وجود، بهطور خودکار از آن استفاده میکند. PHP-FPM افزونهها را هنگام شروع به کار بارگذاری میکند، بنابراین افزونه جدید تا زمانی که pool را restart نکنید، قابل مشاهده نخواهد بود.
sudo systemctl restart php8.3-fpm
php -m | grep redisدر بررسی آخر دقت کنید: php -m ماژولهای نسخه CLI (خط فرمان) PHP را فهرست میکند، در حالی که FPM ممکن است مجموعه متفاوتی را بارگذاری کند. بررسی معتبر، همان ابزار عیبیابی داخلی پلاگین است که در ادامه به آن پرداخته میشود.
تا آگوست 2026، توزیع Ubuntu 24.04 نسخه Redis 7.0.15 را ارائه میدهد که برای کش کردن اشیاء (object cache) مناسب است. اگر به نسخه جدیدتری نیاز دارید، Redis مخزن APT اختصاصی خود را منتشر کرده است.
sudo apt install -y lsb-release curl gpg
curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg
sudo chmod 644 /usr/share/keyrings/redis-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/redis.list
sudo apt update
sudo apt install -y redisاگر توزیع شما Valkey را ارائه میدهد (که پس از تغییر لایسنس در سال 2024 ایجاد شد)، این نرمافزار از همان پروتکل استفاده میکند و تمام موارد زیر بدون تغییر برای آن صدق میکند.
محدود کردن دسترسی به Redis برای جلوگیری از دسترسیهای غیرمجاز
Redis بهصورت پیشفرض فاقد رمز عبور است. هر موجودیتی که بتواند اتصالی به پورت 6379 برقرار کند، قادر است تمام مقادیر کششده را بخواند و دستورات FLUSHALL را اجرا کند. نمونههایی که در معرض اینترنت قرار دارند، ظرف چند ساعت توسط اسکنرها شناسایی میشوند؛ بنابراین تنظیمات شبکه باید پیش از بهینهسازیهای دیگر انجام شود.
فایل /etc/redis/redis.conf را باز کنید و از وجود این خطوط اطمینان حاصل کنید:
bind 127.0.0.1 -::1
protected-mode yesسپس بررسی کنید که چه چیزی واقعاً در حال گوش دادن است، زیرا فایل پیکربندی تنها یک ادعاست و ss مدرک واقعی است.
sudo ss -lntp | grep 6379خروجی 127.0.0.1:6379 همان چیزی است که شما میخواهید. خروجی 0.0.0.0:6379 به این معنی است که Redis در حال پاسخدهی روی اینترفیس عمومی است: خط bind را اصلاح کرده و سرویس را ریاستارت کنید.
زمانی که PHP و Redis روی یک سرور قرار دارند، استفاده از Unix socket بهتر از loopback TCP است. در این حالت، پشته TCP در مسیر قرار نمیگیرد و دسترسی بهجای قوانین فایروال (که ممکن است بعداً تغییر کنند)، توسط مجوزهای فایل تعیین میشود.
unixsocket /run/redis/redis-server.sock
unixsocketperm 770مالکیت سوکت در اختیار کاربر و گروه redis است، بنابراین کاربر وب باید به این گروه اضافه شود.
sudo systemctl restart redis-server
sudo usermod -aG redis www-data
sudo systemctl restart php8.3-fpm
redis-cli -s /run/redis/redis-server.sock pingاین دستور باید PONG را چاپ کند. خروجی Could not connect to Redis at /run/redis/redis-server.sock: Permission denied به این معنی است که تغییر گروه اعمال نشده است. فایل id www-data را بررسی کنید و به یاد داشته باشید که PHP-FPM در حال اجرا، گروههای زمان شروع خود را حفظ میکند؛ به همین دلیل است که ریاستارت در لیست قرار دارد. تا زمانی که از عملکرد صحیح سوکت مطمئن نشدهاید، TCP را فعال نگه دارید تا یک اشتباه تایپی باعث قطع شدن هر دو مسیر دسترسی نشود.
میزان حافظه اختصاصیافته به Redis چقدر باید باشد؟
این مقدار را بر اساس سرور خود محاسبه کنید. Redis بدون maxmemory تا زمانی که حافظه هسته سیستمعامل تمام شود رشد میکند؛ در این حالت OOM killer وارد عمل شده و یک پردازش را متوقف میکند. معمولاً بزرگترین پردازش، یعنی MySQL در سرورهای WordPress، قربانی میشود. journalctl -k | grep -i "out of memory" این توقف را پس از وقوع نشان میدهد و در آن زمان سایت از دسترس خارج شده است.
از کل RAM شروع کنید و مقادیر مصرفی را کسر کنید. MySQL یا MariaDB مقدار innodb_buffer_pool_size را به علاوه بافرهای مربوط به هر اتصال رزرو میکنند. PHP-FPM هزینه pm.max_children را ضربدر اندازه واقعی حافظه اشغالشده توسط یک worker (معمولاً 64 MB تا 128 MB در سایتهای دارای افزونههای زیاد) تحمیل میکند. هسته سیستمعامل و وبسرور نیز به چند صد مگابایت حافظه نیاز دارند. آنچه باقی میماند سقف مجاز شماست و Redis بخشی از آن را دریافت میکند.
بودجهبندی نمونه برای یک VPS با 4 GB رم که یک فروشگاه را میزبانی میکند
اینها ارقام نمونه هستند، نه اندازهگیریهای سرور شما. هر کدام را با مقداری که سرور شما گزارش میدهد جایگزین کنید.
- MariaDB با 1 GB بافر پول: 1024 MB
- PHP-FPM، ده worker با 96 MB برای هر کدام: 960 MB
- هسته سیستمعامل، nginx یا Apache، sshd، لاگها: 512 MB
- باقیمانده: تقریباً 1.5 GB
یک maxmemory معادل 256 MB در اینجا یک شروع منطقی است. این مقدار فضای تنفس کافی باقی میگذارد و یک سایت WordPress بهندرت به بیش از این نیاز دارد.
حالا بهجای حدس زدن، اندازهگیری کنید. پس از یک روز ترافیک واقعی:
redis-cli info memory | grep -E 'used_memory_human|maxmemory_human|maxmemory_policy'
redis-cli dbsizeاگر used_memory_human بسیار پایینتر از حد مجاز شماست، سقف را کاهش دهید و RAM را به MySQL بازگردانید تا از آن استفاده بهتری کند. اگر مقدار در سقف محدودیت ثابت ماند و evicted_keys در طول روز افزایش یافت، آن را بالا ببرید. مقدار را در /etc/redis/redis.conf تنظیم کنید.
maxmemory 256mb
maxmemory-policy allkeys-lruredis-cli config set maxmemory 256mb بلافاصله اعمال میشود اما با راهاندازی مجدد فراموش میشود؛ این همان دامی است که در sysctl -w خام وجود دارد. فایل را ویرایش کنید، سپس sudo systemctl restart redis-server را اجرا کرده و مقدار را دوباره بخوانید. داشتن یک دیوار دوم ارزشمند است: یک محدودیت MemoryMax در unit سیستمعامل systemd مانع از آن میشود که یک Redis با پیکربندی اشتباه، کل سرور را از کار بیندازد. آن را بالاتر از maxmemory تنظیم کنید و هرگز برابر با آن قرار ندهید، زیرا محدودیت cgroup باعث توقف پردازش میشود، نه حذف کلیدها. اگر Redis در یک container در کنار WordPress اجرا میشود، همین رقم باید در محدودیتهای حافظه در فایل Compose قرار گیرد و همین استدلال، انتخاب اجرای دیتابیس در Docker یا روی میزبان را هدایت میکند.
انتخاب آگاهانه سیاست تخلیه (eviction policy)
یک نمونه تازه Redis بهصورت پیشفرض از noeviction استفاده میکند. تنظیمات خود را بررسی کنید:
redis-cli config get maxmemory-policyدر حالت noeviction، یک نمونه کامل (full instance) پذیرش عملیات نوشتن را متوقف کرده و با این پیام پاسخ میدهد:
(error) OOM command not allowed when used memory > 'maxmemory'.این تکخط، بدترین حالت شکست در این راهنما است، زیرا سایت از دسترس خارج نمیشود؛ بلکه کند میشود. هر عملیات نوشتن در کش با شکست مواجه میشود، بنابراین WordPress برای دریافت مقدار به دیتابیس مراجعه میکند، سپس در درخواست بعدی دوباره تلاش میکند آن را ذخیره کند و باز هم شکست میخورد. اکنون سایت علاوه بر تمام پردازشهای اصلی دیتابیس، هزینه یک رفتوبرگشت به Redis را برای هر کلید پرداخت میکند. هیچ بخشی در پنل مدیریت WordPress این وضعیت را گزارش نمیکند. این رشته در لاگ خطاهای PHP ظاهر میشود، بنابراین اگر پس از افزودن کش، سایت کند شد، عبارت OOM command not allowed را جستجو (grep) کنید.
allkeys-lru گزینه پیشفرض مناسب در اینجا است. Redis در زمان کمبود حافظه، کلیدی که کمترین استفاده اخیر را داشته حذف میکند؛ این دقیقاً همان چیزی است که یک object cache به آن نیاز دارد، زیرا هر مقدار موجود در آن، کپی دادهای است که همچنان در MySQL وجود دارد. از دست دادن یک کلید، هزینه یک کوئری را دارد، اما امتناع از نوشتن، هزینه تمام کوئریها را در هر درخواست تحمیل میکند تا زمانی که شخصی متوجه مشکل شود.
از سیاستهای volatile-* برای این کار اجتناب کنید. این سیاستها فقط کلیدهایی را در نظر میگیرند که دارای تاریخ انقضا (expiry) هستند و مستندات Redis بیان میکنند که در صورت نبود کلید دارای انقضا، این سیاستها مشابه noeviction عمل میکنند. WordPress اکثر ورودیهای object cache را بدون TTL ذخیره میکند، بنابراین استفاده از volatile-lru برای object cache میتواند منجر به پر شدن حافظه و امتناع از نوشتن شود. allkeys-lfu جایگزین مناسبی است اگر ترافیک شما بهطور مکرر به مجموعه کوچکی از کلیدها برخورد میکند، زیرا تخلیه را بر اساس فراوانی (frequency) انجام میدهد نه تازگی (recency). یکی را آگاهانه انتخاب کنید و دلیل آن را یادداشت نمایید.
ماندگاری (Persistence): مگر دلیلی دارید، آن را غیرفعال کنید
بسته redis.conf قابلیت RDB snapshots را با خطوطی مانند save 900 1 فعال میکند و فایل append-only را غیرفعال میگذارد. برای یک کش شیء (object cache) خالص، اسنپشاتها هیچ سودی ندارند. دادهها طبق تعریف قابل بازسازی هستند و کشی که از یک فایل 20 دقیقهای بازیابی شود، مجموعهای از مقادیر قدیمی است که WordPress به آنها اعتماد خواهد کرد.
اسنپشاتها هزینه هم دارند. BGSAVE فرآیند را fork میکند و مکانیزم copy-on-write باعث میشود هنگام نوشتن توسط فرزند، مصرف حافظه بهشدت افزایش یابد. در یک VPS کوچک، این موضوع در لاگ Redis نمایان میشود:
Can't save in background: fork: Cannot allocate memoryو اغلب این هشدار در زمان راهاندازی ظاهر میشود که به این معناست که Redis به شما میگوید احتمالاً fork در آینده با شکست مواجه خواهد شد:
WARNING overcommit_memory is set to 0! Background save may fail under low memory condition.برای غیرفعال کردن اسنپشاتها، یک زمانبندی ذخیرهسازی خالی در /etc/redis/redis.conf تنظیم کنید، سرویس را restart کنید و تأیید کنید که مقدار بازگشتی خالی است.
save ""sudo systemctl restart redis-server
redis-cli config get saveماندگاری را فقط در صورتی حفظ کنید که همان instance دادهای را نگه میدارد که نمیتوانید دوباره بسازید، مانند صفهای کاری (job queue) یا شمارندههای محدودکننده نرخ (rate-limit counters). در این صورت، این دو را از هم جدا کنید. کش نیاز به حذف کلیدها (eviction) دارد و دادههای ماندگار نیاز به حفظ کلیدها دارند، و maxmemory به همراه eviction روی کل instance اعمال میشود، نه روی یک دیتابیس index خاص. داشتن دو instance روی دو socket، راهکار تمیز و اصولی است.
نصب افزونه و درک نحوه عملکرد drop-in
wp plugin install redis-cache --activate
wp redis enable
wp redis statuswp redis enable در صورت موفقیت، Object cache enabled. را چاپ میکند. کاری که این دستور در واقع انجام میدهد، کپی کردن wp-content/plugins/redis-cache/includes/object-cache.php به wp-content/object-cache.php است. این کپی همان فایل drop-in است و بخش اصلی عملیات توسط همین فایل انجام میشود. وردپرس فایل wp-content/object-cache.php را در مراحل بسیار اولیه، پیش از اجرای کد هرگونه افزونهای بارگذاری میکند؛ به همین دلیل است که کش برای کل درخواست در دسترس قرار میگیرد. یک افزونه فعال که فایل drop-in در جای خود نداشته باشد، هیچ چیزی را کش نمیکند.
پیامهای خطا مشخص میکنند که کدام بخش دچار مشکل شده است. Object cache could not be enabled. به این معناست که عملیات کپی با شکست مواجه شده، زیرا wp-content توسط کاربری که WP-CLI را اجرا میکند، قابل نوشتن نیست. A foreign object cache drop-in was found. به این معناست که یک افزونه کش دیگر از قبل مالک آن نام فایل است و راهحل آن wp redis update-dropin میباشد. پیامی که به Redis server is unreachable: ختم میشود و پس از آن خطای کلاینت میآید، نشاندهنده اشتباه بودن تنظیمات اتصال است؛ بنابراین به redis-cli ping بازگردید.
اگر عملیات کپی به دلیل مجوزهای دسترسی (permissions) با شکست مواجه شد، فایل را بهصورت دستی در مسیر مربوطه قرار دهید و مالکیت آن را به کاربر وب (web user) اختصاص دهید.
cp wp-content/plugins/redis-cache/includes/object-cache.php wp-content/object-cache.php
sudo chown www-data:www-data wp-content/object-cache.phpحذف افزونه باعث حذف فایل drop-in نمیشود. ابتدا wp redis disable را اجرا کنید که Object cache disabled. را چاپ کرده و فایل را حذف میکند. اگر دایرکتوری افزونه را حذف کنید در حالی که فایل drop-in باقی مانده باشد، سایت به اجرای کد کش قدیمی ادامه میدهد، بدون اینکه افزونهای برای بهروزرسانی آن وجود داشته باشد.
تنظیمات اتصال در wp-config.php
این موارد را پیش از خطی که شامل /* That's all, stop editing! */ است اضافه کنید، زیرا ثابتهایی که پس از آن تعریف شوند، تأثیری نخواهند داشت.
define( 'WP_REDIS_HOST', '127.0.0.1' );
define( 'WP_REDIS_PORT', 6379 );
define( 'WP_REDIS_DATABASE', 0 );
define( 'WP_REDIS_PREFIX', 'shop_prod:' );برای Unix socket، طرح (scheme) و مسیر را تنظیم کنید. در این حالت، host و port نادیده گرفته میشوند.
define( 'WP_REDIS_SCHEME', 'unix' );
define( 'WP_REDIS_PATH', '/run/redis/redis-server.sock' );
define( 'WP_REDIS_PREFIX', 'shop_prod:' );WP_REDIS_MAXTTL برای هر کلید یک زمان انقضا به ثانیه تعیین میکند. شما با وجود allkeys-lru به این مورد نیازی ندارید، اما اگر میخواهید یک حد بالای سختگیرانه برای میزان قدیمی بودن مقادیر کششده داشته باشید، مفید است.
یک Redis، چندین سایت: پیشوندها و پایگاههای داده
Redis بهصورت پیشفرض شانزده پایگاه داده شمارهگذاریشده و یک فضای کلید (keyspace) تخت در هر کدام ارائه میدهد. دو نصب WordPress که بدون پیشوند به پایگاه داده 0 متصل شده باشند، نام کلیدهای یکسانی را در فضای مشابه مینویسند؛ در نتیجه یک سایت میتواند تنظیمات سایت دیگر را بخواند و از آنها استفاده کند. برای هر سایت یک پیشوند اختصاصی تعیین کنید.
define( 'WP_REDIS_PREFIX', 'shopA_prod:' );
define( 'WP_REDIS_DATABASE', 1 );پیشوند، نام کلیدها را از هم جدا میکند. اندیس پایگاه داده، فضاهای کلید را تفکیک میکند که هنگام پاکسازی (flush) اهمیت دارد: خالی کردن یک اندیس، سایر اندیسها را دستنخورده باقی میگذارد. افزونه همچنین WP_REDIS_SELECTIVE_FLUSH را مستند کرده است که بهجای پاک کردن کل پایگاه داده، فقط کلیدهای منطبق با پیشوند شما را حذف میکند، هرچند این کار مستلزم اسکن کردن کلیدها است.
آنچه پیشوندها و اندیسها جدا نمیکنند، حافظه است. maxmemory و سیاست تخلیه (eviction policy) برای کل نمونه (instance) اعمال میشوند؛ بنابراین یک سایت پرمصرف میتواند کلیدهای یک سایت کممصرف را از حافظه خارج کند بدون اینکه هیچکدام گزارشی از این اتفاق ارائه دهند. سایتهایی که نباید بر یکدیگر تأثیر بگذارند، به نمونههای Redis مجزا نیاز دارند که هر کدام سوکت و محدودیت حافظه مخصوص به خود را داشته باشند.
جلوگیری از تداخل محیط staging با کش محیط production
سایت staging معمولاً نسخهای از فایلها و دیتابیس production است، به این معنی که نسخهای از wp-config.php است که همان پیشوند و همان ایندکس دیتابیس را حمل میکند. اگر آن را به همان Redis متصل کنید، کلیدهای production را با مقادیر staging بازنویسی میکند. در نتیجه، یک قیمت آزمایشی یا یک گزینه تغییریافته بدون هیچ عملیات deploy و بدون هیچ ردی، در سایت زنده ظاهر میشود.
برای هر محیط بهصورت دستی یک salt تعریف کنید. در فایل wp-config.php محیط staging:
define( 'WP_REDIS_PREFIX', 'shop_staging:' );
define( 'WP_REDIS_DATABASE', 5 );بهتر از آن، برای staging یک instance جداگانه از Redis در نظر بگیرید یا کلاً object cache را غیرفعال کنید. استفاده از define( 'WP_REDIS_DISABLED', true ); کش را در زمان اجرا غیرفعال میکند و drop-in را در جای خود باقی میگذارد؛ این سریعترین راه برای اثبات این است که آیا یک باگ مربوط به کش هست یا خیر.
آموزشهای قدیمی برای این کار WP_CACHE_KEY_SALT را تنظیم میکردند. فایل readme این افزونه، آن ثابت (constant) را منسوخشده اعلام کرده و WP_REDIS_PREFIX را جایگزین آن کرده است، بنابراین از نام جدید استفاده کنید.
به جای اعتماد کردن، آن را تایید کنید
با ابزارهای تشخیص خودِ افزونه شروع کنید.
wp redis statusخطی که بیشترین اهمیت را دارد Drop-in است. Drop-in: Valid به این معنی است که وردپرس در حال بارگذاری فایل این افزونه است. Drop-in: Not installed به این معنی است که کپیسازی هرگز انجام نشده و سایت هیچ کش پایداری ندارد، حتی اگر صفحه مدیریت سبز به نظر برسد. Status وضعیت اتصال را گزارش میدهد و Client نام افزونه در حال استفاده را ذکر میکند؛ جایی که باید تایید کنید از PhpRedis استفاده میشود نه Predis.
سپس مستقیماً از هسته وردپرس سوال کنید، زیرا برای هسته اهمیتی ندارد که افزونه چه فکری میکند.
wp eval 'var_dump( wp_using_ext_object_cache() );'bool(true) به این معنی است که هسته در حال گفتگو با یک کش شیء (object cache) خارجی است.
سپس با استفاده از پیشوندی که پیکربندی کردهاید، ثابت کنید که کلیدها در حال رسیدن هستند.
redis-cli -n 0 dbsize
redis-cli -n 0 --scan --pattern 'shop_prod:*' | headافزایش dbsize در حین کلیک کردن در سایت، گواه این موضوع است. صفر بودن کلیدها با وجود یک drop-in معتبر، به این معنی است که اتصال در سکوت در حال شکست است یا پیشوند همان چیزی نیست که شما تصور میکنید.
در نهایت، نگاهی به آنچه Redis برای شما اندازهگیری میکند بیندازید.
redis-cli info stats | grep -E 'keyspace_hits|keyspace_misses|evicted_keys|expired_keys'نرخ اصابت (hit ratio) برابر با keyspace_hits / (keyspace_hits + keyspace_misses) است و مستندات Redis آن فرمول را ارائه میدهد. آن را با دو هشدار بخوانید. شمارندهها کل نمونه (instance) را از زمان آخرین راهاندازی مجدد پوشش میدهند، بنابراین همه سایتها و برنامههایی که از آن استفاده میکنند را با هم ترکیب میکنند. همچنین، این نرخ بلافاصله پس از پاکسازی (flush) یا راهاندازی مجدد بیمعنی است، زیرا کش هنوز در حال پر شدن است. اجازه دهید یک روز کاری عادی با ترافیک معمولی سپری شود.
عدد خود را با نرخ اصابت یا تعداد کوئریهای منتشر شده توسط یک شرکت میزبانی مقایسه نکنید. آنها سایتها و مجموعه افزونههای خودشان را توصیف میکنند. رقمی که اهمیت دارد، رقم خود شماست که قبل و بعد از فعالسازی، در صفحهای که کش صفحه (page cache) نمیتواند آن را سرویسدهی کند، اندازهگیری شده است.
curl -o /dev/null -s -w '%{time_starttransfer}\n' -b cookies.txt https://example.com/my-account/آن را با یک کوکی لاگین، چندین بار، با کش خاموش (WP_REDIS_DISABLED) و سپس روشن اجرا کنید. آن تفاوت، نتیجه نهایی شماست.
زمانی که Redis باعث کندی WordPress میشود
یک نمونه کامل با سیاست اشتباه، عامل اصلی است که در بالا به آن اشاره شد: OOM command not allowed when used memory > 'maxmemory'. در لاگ، و سایتی که هم هزینه دیتابیس و هم هزینه کش را میپردازد.
Redis روی یک میزبان دیگر، عامل دوم است. WordPress در هر درخواست، صدها فراخوانی object cache انجام میدهد. اگر یک درخواست 500 فراخوانی داشته باشد و هر رفتوبرگشت 1 میلیثانیه زمان ببرد، این یعنی نیم ثانیه انتظار که در صورت استفاده از سوکت محلی وجود نداشت. Redis را روی همان سرور نگه دارید، یا از یک شبکه خصوصی با تأخیر زیر یک میلیثانیه استفاده کنید. اینکه در حالت اجرای روی یک سرور، چقدر از مزایای هسته سیستمعامل بهرهمند میشوید، بحث جداگانهای است: زمانبندی آگاه از کش که در Linux 7.2 اضافه شد تلاش میکند فرآیندهای پرارتباط مانند PHP-FPM و Redis را روی هستههایی نگه دارد که کش مشترک دارند، و یک VPS guest نسبت به سختافزار فیزیکی (bare metal)، بهره کمتری از این قابلیت میبرد.
یک جدول options با حجم زیاد autoload، عامل سوم است و در سایتهای قدیمی رایج است. WordPress تمام گزینههای autoload را به عنوان یک کلید کش میکند، بنابراین یک مگابایت از آنها در هر درخواست از طریق اتصال منتقل میشود. آن را اندازهگیری کنید:
wp db query "SELECT ROUND(SUM(LENGTH(option_value))/1024) AS kb FROM wp_options WHERE autoload IN ('yes','on','auto','auto-on');"نسخه WordPress 6.6 مقادیر autoload جدیدی اضافه کرد، بنابراین یک کوئری قدیمی که فقط 'yes' را مطابقت میدهد، در نصبهای مدرن گزارش ناقصی ارائه میدهد. هر چیزی فراتر از یک مگابایت، مشکلی است که باید در جدول options حل شود، نه در Redis.
یک restart همه چیز را خالی میکند، بنابراین دقایق پس از systemctl restart redis-server تماماً شامل miss و فعالیت دیتابیس است. زمانی که ترافیک کم است، restart کنید. همچنین یک object cache مانع از اجرای wp-cron.php در هنگام بارگذاری صفحات توسط بازدیدکنندگان نمیشود، که خود منبعی برای درخواستهای کند است: در همین حین، WP-Cron را به یک system cron job واقعی منتقل کنید.
نگهداری سیستم
پس از هر بار استقرار (deploy) که گزینهها یا کدهای پوسته (theme) را تغییر میدهد، با استفاده از wp cache flush حافظه موقت را پاکسازی کنید. اگر پس از بهروزرسانی یک افزونه، فایل drop-in بهطور خودکار بهروز نشد، حتماً wp redis update-dropin را اجرا کنید؛ چرا که استفاده از یک drop-in مربوط به نسخه قدیمی افزونه در کنار نسخه جدید، منبع اصلی رفتارهای غیرعادی است. برای نظارت زنده بر سرور از redis-cli --stat استفاده کنید که در هر ثانیه یک خط خروجی چاپ میکند. دستور redis-cli monitor تمامی دستورات را چاپ میکند و در نمونههای (instance) پرمشغله، مصرف CPU بالایی دارد؛ بنابراین فقط برای چند ثانیه جهت بازتولید مشکل از آن استفاده کرده و سپس متوقفش کنید.
یک عدد نهایی که دانستن آن مفید است: redis-cli info clients مقدار connected_clients را گزارش میدهد. از آنجایی که PHP-FPM برای هر worker یک اتصال نگه میدارد، این عدد باید با pm.max_children شما همخوانی داشته باشد و نباید از آن به میزان یک مرتبه بزرگی (order of magnitude) فراتر رود. اگر چنین شد، یعنی فرآیندی در حال باز کردن اتصالات است و آنها را نمیبندد.
FAQ
آیا با وجود Redis object cache، همچنان به page cache نیاز دارم؟
بله، برای ترافیک ناشناس. یک page cache فایلهای HTML ذخیرهشده را بدون اجرای PHP ارائه میدهد که همیشه از اجرای وردپرس با یک object cache گرم، کمهزینهتر است. object cache به درخواستهایی رسیدگی میکند که page cache باید از آنها صرفنظر کند: کاربران واردشده، سبد خرید، تسویه حساب و wp-admin. در یک فروشگاه یا سایت عضویتمحور، استفاده از هر دو توصیه میشود. در سایتی که بازدیدکنندگان هرگز وارد نمیشوند، page cache تقریباً تمام کار را انجام میدهد.
چه مقدار حافظه باید به Redis برای وردپرس اختصاص دهم؟
این مقدار را بر اساس سرور خود تعیین کنید، نه با کپی کردن یک عدد ثابت. کل RAM را در نظر بگیرید، MySQL buffer pool و بافرهای هر اتصال را از آن کم کنید، pm.max_children ضربدر اندازه resident یک worker از نوع PHP-FPM را کسر کنید و چند صد مگابایت برای هسته سیستمعامل و وبسرور کنار بگذارید. بخشی از باقیمانده را به Redis اختصاص دهید، سپس پس از یک روز ترافیک، used_memory_human را در redis-cli info memory بررسی کرده و تنظیمات را اصلاح کنید. یک سایت وردپرسی معمولاً به دهها مگابایت حافظه نیاز دارد، بنابراین یک maxmemory با ظرفیت 256 MB برای شروع روی یک سرور 4 GB بسیار مناسب است.
چرا پس از فعالسازی Redis object cache، سایت من کندتر شد؟
دلیل معمول این است که instance پر شده و از سیاست noeviction استفاده میکند. Redis نوشتنهای جدید را رد کرده و OOM command not allowed when used memory > 'maxmemory'. برمیگرداند، بنابراین وردپرس برای هر مقدار به دیتابیس بازمیگردد و علاوه بر آن، یک رفتوبرگشت بیهوده به Redis نیز متحمل میشود. redis-cli config get maxmemory-policy را بررسی کنید، allkeys-lru را تنظیم نمایید و مطمئن شوید که maxmemory بسیار کوچک نیست. دلایل رایج دیگر، قرار داشتن سرور Redis روی یک میزبان راه دور است که در آن صدها رفتوبرگشت در هر درخواست جمع میشوند، یا وجود یک مقدار autoloaded options چند مگابایتی که در هر درخواست از طریق شبکه منتقل میشود.
آیا چندین سایت وردپرسی میتوانند از یک سرور Redis مشترک استفاده کنند؟
بله، با رعایت احتیاط. برای هر سایت یک WP_REDIS_PREFIX منحصربهفرد تعیین کنید تا نام کلیدها با هم تداخل نداشته باشند، و از یک WP_REDIS_DATABASE متفاوت استفاده کنید تا پاکسازی (flush) یک سایت، دادههای سایت دیگر را حذف نکند. آنچه همچنان مشترک باقی میماند حافظه است: maxmemory و سیاست حذف کلیدها (eviction) برای کل instance اعمال میشود، بنابراین یک سایت پربازدید میتواند کلیدهای یک سایت کمبازدید را حذف کند. سایتهایی که نباید بر یکدیگر تأثیر بگذارند، به instanceهای جداگانه Redis با محدودیتهای خاص خود نیاز دارند.
آیا حذف فایل wp-content/object-cache.php ایمن است؟
بله. این یک فایل drop-in است و بخشی از هسته وردپرس نیست؛ حذف آن باعث میشود وردپرس به کش داخلی و مبتنی بر هر درخواست خود بازگردد. سایت به کار خود ادامه میدهد و صرفاً کوئریهای دیتابیس بیشتری انجام میدهد. استفاده از wp redis disable را ترجیح دهید که فایل را بهطور تمیز حذف کرده و Object cache disabled. را گزارش میدهد. حذف دستی این فایل در شرایط اضطراری، اگر Redis از دسترس خارج شده یا دچار مشکل شده باشد و به پنل مدیریت دسترسی ندارید، اقدام درستی است.