VPS-এ WordPress-এর জন্য Redis object cache সেটআপ
নিজের VPS-এ WordPress-এর Redis object cache নিরাপদে সেটআপ করুন: localhost-এ bind, maxmemory ও eviction policy নির্ধারণ, এবং cache সত্যিই কাজ করছে কি না যাচাই করুন।
WordPress-এর জন্য Redis object cache কী করে
WordPress-এর জন্য Redis object cache database query-এর ফলাফল memory-তে সংরক্ষণ করে। ফলে পরের request-এ WordPress আবার MySQL-কে query না করে Redis থেকে ফলাফল পড়ে। WordPress core-এ ইতিমধ্যে একটি object cache আছে, WP_Object_Cache, কিন্তু সেটি PHP memory-তে থাকে এবং request শেষ হলে মুছে যায়। একটি drop-in file এই cache-কে এমন একটি cache দিয়ে প্রতিস্থাপন করে, যা Redis-এর সঙ্গে যোগাযোগ করে। তাই এক request থেকে পরের request পর্যন্ত cache বজায় থাকে।
Object caching এবং page caching এক জিনিস নয়। এই পার্থক্যটি নির্ধারণ করে এই guide আপনার জন্য কতটা কার্যকর। Page cache কোনো URL-এর সম্পূর্ণ HTML সংরক্ষণ করে এবং PHP একেবারেই চালানো ছাড়া সেটি আবার সরবরাহ করে। Redis যা করতে পারে, তার চেয়ে এটি দ্রুত। Logged-in নয় এমন visitor-দের জন্য এটি কার্যকর। কেউ login করলে, cart-এ কোনো item যোগ করলে বা admin খুললে page cache আর request পরিচালনা করে না। তখন WordPress সম্পূর্ণ request চালায়: bootstrap, plugin এবং query। Object cache ওই request-এর খরচ কমায়। Page cache যে traffic পরিচালনা করতে পারে না, object cache সেই traffic-এর জন্য ব্যবহৃত হয়: logged-in session, cart, checkout এবং wp-admin। WooCommerce shop-এ সাধারণত এটাই সবচেয়ে ব্যয়বহুল traffic।
দুটি cache একসঙ্গে ব্যবহার করা যায় এবং ব্যস্ত site-এ দুটিই প্রয়োজন। আপনি কোন সমস্যার সমাধান করছেন তা স্পষ্টভাবে নির্ধারণ করুন। Anonymous reader-সহ একটি brochure site-এর প্রায় সম্পূর্ণ গতি page cache থেকে আসে। সেখানে Redis যোগ করলে খুব সামান্য পরিবর্তন হয়।
শুরু করার আগে একটি সীমাবদ্ধতা মনে রাখুন। Object cache ধীর query-কে দ্রুত করে না। এটি আগে সম্পন্ন হওয়া query-এর পুনরাবৃত্তি বন্ধ করে। Cache miss-এর পর প্রথম request-এ সম্পূর্ণ খরচ বহন করতে হয়। তাই কোনো plugin unindexed query চালালে, প্রতিটি cache lifetime-এ সেটি অন্তত একবার চলবেই।
প্রথমে যা প্রয়োজন
- shell এবং
sudo-সহ একটি Linux VPS। কোনো control panel প্রয়োজন নেই। - PHP-FPM দিয়ে পরিবেশিত WordPress, যেমন Ubuntu 24.04-এ একটি LAMP stack।
- সার্ভারে WP-CLI। এখানে প্রতিটি ধাপের admin screen-এ সমতুল্য পদ্ধতি আছে, তবে shell সংস্করণটি দ্রুত।
- PHP-এর একই মেশিনে Redis। কম latency-ই মূল উদ্দেশ্য; network hop হলে সেই সুবিধা নষ্ট হয়।
নিচের কমান্ডগুলো Ubuntu 24.04, PHP 8.3 এবং www-data web user-এর জন্য লেখা। আপনার সার্ভার অনুযায়ী PHP version এবং user পরিবর্তন করুন। wp কমান্ডগুলো WordPress directory থেকে চালান, যে directory-তে wp-config.php আছে।
Redis এবং PHP extension ইনস্টল করুন
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 হলো PECL-এর C extension PhpRedis। এটি pure PHP-ভিত্তিক Predis-এর চেয়ে দ্রুত। plugin উপস্থিত থাকলে এটি স্বয়ংক্রিয়ভাবে সেটি ব্যবহার করে। PHP-FPM শুরু হওয়ার সময় extension লোড করে। তাই নতুন extension যোগ করার পর pool restart না করা পর্যন্ত সেটি কার্যকর হবে না।
sudo systemctl restart php8.3-fpm
php -m | grep redisশেষের পরীক্ষা সম্পর্কে সতর্ক থাকুন। php -m command line PHP-এর module তালিকাভুক্ত করে। FPM ভিন্ন module সেট লোড করতে পারে। প্রকৃত যাচাই করতে plugin-এর নিজস্ব diagnostics ব্যবহার করুন। এটি পরের অংশে রয়েছে।
August 2026 অনুযায়ী, Ubuntu 24.04-এ Redis 7.0.15 package রয়েছে। object cache-এর জন্য এটি যথেষ্ট। এর পরিবর্তে বর্তমান release ব্যবহার করতে চাইলে Redis নিজস্ব APT repository প্রকাশ করে।
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আপনার distribution-এ Valkey থাকলে সেটি ব্যবহার করতে পারেন। 2024 সালের licence পরিবর্তনের পরে এই fork শুরু হয়। এটি একই protocol ব্যবহার করে। তাই নিচের সব নির্দেশনা অপরিবর্তিতভাবে প্রযোজ্য।
Redis bind করুন, যাতে অন্য কোনো সংযোগ এটি ব্যবহার করতে না পারে
Redis-এ ডিফল্টভাবে কোনো password থাকে না। যে কোনো client port 6379-এ সংযোগ খুলতে পারলে প্রতিটি cached value পড়তে এবং FLUSHALL চালাতে পারে। Internet-এ উন্মুক্ত instance কয়েক ঘণ্টার মধ্যেই scanner-এর সন্ধানে চলে আসে। তাই tuning-এর আগে network setting ঠিক করুন।
/etc/redis/redis.conf খুলে এই লাইনগুলো নিশ্চিত করুন:
bind 127.0.0.1 -::1
protected-mode yesএরপর সত্যিই কোন address-এ listening চলছে তা পরীক্ষা করুন। Configuration file-টি শুধু একটি দাবি, আর ss হলো প্রমাণ।
sudo ss -lntp | grep 6379127.0.0.1:6379-ই প্রত্যাশিত ফল। 0.0.0.0:6379 মানে Redis public interface-এ উত্তর দিচ্ছে। bind লাইন ঠিক করে Redis restart করুন।
PHP এবং Redis একই server-এ থাকলে loopback TCP-এর চেয়ে Unix socket ভালো। এতে সংযোগপথে TCP stack থাকে না। Access একটি firewall rule-এর বদলে file permission দিয়ে নিয়ন্ত্রিত হয়, যা পরে পরিবর্তিত হয়ে যেতে পারে।
unixsocket /run/redis/redis-server.sock
unixsocketperm 770Socket-টির owner এবং group হলো redis user ও group। তাই web user-কে ওই group-এ যোগ করতে হবে।
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 মানে group কার্যকর হয়নি। id www-data পরীক্ষা করুন। মনে রাখবেন, চলমান PHP-FPM শুরু হওয়ার সময় যে group পেয়েছিল, সেটিই ধরে রাখে। এ কারণেই তালিকায় restart রয়েছে। Socket কাজ করছে নিশ্চিত না হওয়া পর্যন্ত TCP চালু রাখুন। তা না হলে একটি typo একসঙ্গে উভয় সংযোগপথ বন্ধ করে দিতে পারে।
Redis-কে কত মেমরি দেওয়া উচিত?
আপনার নিজের সার্ভার থেকে সংখ্যাটি নির্ধারণ করুন। কোনো maxmemory ছাড়া Redis মেমরি বাড়াতে থাকে, যতক্ষণ না kernel-এর মেমরি শেষ হয় এবং OOM killer একটি process বন্ধ করে। সাধারণত সবচেয়ে বড় process-টিই বন্ধ হয়। WordPress server-এ সেটি প্রায়ই MySQL। journalctl -k | grep -i "out of memory" পরে সেই বন্ধ হওয়ার ঘটনা দেখায়। ততক্ষণে site down হয়ে যায়।
মোট RAM থেকে অন্যান্য ব্যবহারের মেমরি বাদ দিয়ে শুরু করুন। MySQL বা MariaDB innodb_buffer_pool_size এবং প্রতি-connection buffer-এর জন্য মেমরি সংরক্ষণ করে। PHP-FPM-এর খরচ হলো pm.max_children-এর সঙ্গে একটি worker-এর প্রকৃত resident size গুণ করা। Plugin বেশি থাকা site-এ এটি সাধারণত 64 MB থেকে 128 MB হয়। Kernel এবং web server-এর জন্য কয়েকশ MB রাখুন। অবশিষ্ট অংশই আপনার সর্বোচ্চ সীমা। Redis সেই সীমার একটি অংশ পাবে।
4 GB VPS-এ একটি shop চালানোর উদাহরণ বাজেট
এগুলো উদাহরণস্বরূপ দেওয়া সংখ্যা। আপনার server থেকে মাপা সংখ্যা নয়। প্রতিটি সংখ্যা আপনার server-এ পাওয়া মান দিয়ে প্রতিস্থাপন করুন।
- 1 GB buffer pool-সহ MariaDB: 1024 MB
- PHP-FPM, প্রতিটি 96 MB-এর 10টি worker: 960 MB
- Kernel, nginx বা Apache, sshd, logging: 512 MB
- অবশিষ্ট: প্রায় 1.5 GB
সেখানে maxmemory 256 MB একটি যুক্তিসঙ্গত প্রাথমিক সীমা। এতে পর্যাপ্ত অতিরিক্ত মেমরি থাকে। একটি WordPress site-এর সাধারণত এর বেশি প্রয়োজন হয় না।
এখন অনুমান না করে মাপুন। প্রকৃত traffic-এর এক দিন পরে:
redis-cli info memory | grep -E 'used_memory_human|maxmemory_human|maxmemory_policy'
redis-cli dbsizeused_memory_human যদি আপনার সীমার তুলনায় অনেক কম থাকে, সীমা কমিয়ে RAM MySQL-কে দিন। MySQL এটি আরও কার্যকরভাবে ব্যবহার করবে। সীমায় পৌঁছে থাকলে এবং evicted_keys সারাদিন বাড়তে থাকলে, সীমা বাড়ান। মানটি /etc/redis/redis.conf-এ সেট করুন।
maxmemory 256mb
maxmemory-policy allkeys-lruredis-cli config set maxmemory 256mb এখনই কার্যকর হয়। পরবর্তী restart-এ এটি হারিয়ে যায়। এটি একটি খালি sysctl -w-এর মতোই একই সমস্যা। ফাইলটি সম্পাদনা করুন। এরপর sudo systemctl restart redis-server চালান। তারপর মানটি আবার পড়ে যাচাই করুন। দ্বিতীয় একটি সীমা রাখা ভালো: systemd unit-এ MemoryMax cap misconfigured Redis-কে পুরো server অচল করে দেওয়া থেকে আটকায়। এটি maxmemory-এর চেয়ে বেশি সেট করুন, কখনো সমান নয়। কারণ cgroup limit key evict না করে process বন্ধ করে দেয়। WordPress-এর পাশে container-এ Redis চললে একই সংখ্যা আপনার Compose file-এর memory limits-এ দিতে হবে। একই যুক্তি database Docker-এ চালাবেন, নাকি host-এ—এই সিদ্ধান্তের ক্ষেত্রেও প্রযোজ্য।
ইচ্ছাকৃতভাবে eviction policy নির্বাচন করুন
নতুন Redis-এর ডিফল্ট হলো noeviction। আপনার সেটিং পরীক্ষা করুন:
redis-cli config get maxmemory-policynoeviction ব্যবহার করলে instance সম্পূর্ণ ভরে গেলে আর write গ্রহণ করে না এবং এভাবে উত্তর দেয়:
(error) OOM command not allowed when used memory > 'maxmemory'.এই গাইডে এটিই সবচেয়ে খারাপ failure mode, কারণ site বন্ধ হয় না। এটি ধীর হয়ে যায়। প্রতিটি cache write ব্যর্থ হয়। তাই WordPress value-এর জন্য আবার database-এ যায়, পরের request-এ সেটি সংরক্ষণ করার চেষ্টা করে এবং আবারও ব্যর্থ হয়। এখন site-কে তার আগের সব database কাজের পাশাপাশি প্রতিটি key-এর জন্য Redis-এ একটি round trip করতে হয়। WordPress admin-এর কোনো অংশ আপনাকে জানায় না যে এটি ঘটছে। এই string PHP error log-এ দেখা যায়। তাই cache যোগ করার পর site ধীর হয়ে গেলে OOM command not allowed খুঁজে দেখুন।
এখানে allkeys-lru-ই সঠিক default। memory কম থাকলে Redis least recently used key বাদ দেয়। object cache-এর জন্য এটিই উপযুক্ত, কারণ এর প্রতিটি value হলো MySQL-এ এখনও থাকা data-এর একটি copy। একটি key হারালে একটি query-এর খরচ হয়। কিন্তু write প্রত্যাখ্যান করলে কেউ বিষয়টি লক্ষ্য না করা পর্যন্ত প্রতিটি request-এ প্রতিটি query-এর খরচ চলতে থাকে।
এই কাজের জন্য volatile-* policy এড়িয়ে চলুন। এগুলো শুধু expiry থাকা key বিবেচনা করে। কোনো key-তে expiry না থাকলে Redis-এর documentation অনুযায়ী এগুলো noeviction-এর মতো আচরণ করে। WordPress অধিকাংশ object cache entry কোনো TTL ছাড়াই সংরক্ষণ করে। তাই object cache-এ volatile-lru পূর্ণ হয়ে write প্রত্যাখ্যান শুরু করতে পারে। আপনার traffic যদি অল্প কিছু key-তে খুব ঘন ঘন আসে, তাহলে allkeys-lfu একটি গ্রহণযোগ্য বিকল্প। এটি recency-এর বদলে frequency অনুযায়ী key বাদ দেয়। একটি policy ইচ্ছাকৃতভাবে নির্বাচন করুন এবং কেন সেটি বেছে নিয়েছেন তা লিখে রাখুন।
Persistence: leave it off unless you have a reason
The packaged redis.conf enables RDB snapshots with lines like save 900 1, and leaves the append-only file off. For a pure object cache, snapshots buy nothing. The data is regenerable by definition, and a cache restored from a twenty-minute-old file is a set of stale values that WordPress will trust.
Snapshots also cost. BGSAVE forks the process, and copy-on-write means memory use can rise sharply while the child writes. On a small VPS that shows up in the Redis log:
Can't save in background: fork: Cannot allocate memoryand often this warning at startup, which is Redis telling you the fork is likely to fail later:
WARNING overcommit_memory is set to 0! Background save may fail under low memory condition.To turn snapshots off, set an empty save schedule in /etc/redis/redis.conf, restart, and confirm the value came back empty.
save ""sudo systemctl restart redis-server
redis-cli config get saveKeep persistence only if the same instance holds something you cannot rebuild, such as a job queue or rate-limit counters. In that case split the two. A cache wants keys evicted and durable data wants keys kept, and maxmemory plus eviction applies to the whole instance, not to one database index. Two instances on two sockets is the clean answer.
প্লাগইন ইনস্টল করুন এবং drop-in বুঝে নিন
wp plugin install redis-cache --activate
wp redis enable
wp redis statusসফল হলে wp redis enable, Object cache enabled. মুদ্রণ করে। এটি আসলে wp-content/plugins/redis-cache/includes/object-cache.php-কে wp-content/object-cache.php-এ কপি করে। ওই কপিটিই drop-in, এবং কাজটি drop-in-ই করে। WordPress খুব শুরুর পর্যায়ে wp-content/object-cache.php লোড করে, কোনো plugin code চালানোর আগেই। এ কারণেই পুরো request-এর জন্য cache উপলভ্য থাকে। drop-in না থাকলে সক্রিয় plugin কোনো cache সংরক্ষণ করে না।
ব্যর্থতার বার্তাগুলো জানায় কোন অংশে সমস্যা হয়েছে। Object cache could not be enabled. মানে কপি ব্যর্থ হয়েছে। অর্থাৎ WP-CLI চালানো user-এর জন্য wp-content writable নয়। A foreign object cache drop-in was found. মানে অন্য কোনো caching plugin ইতিমধ্যে ওই filename ব্যবহার করছে। সমাধান হলো wp redis update-dropin। Redis server is unreachable: দিয়ে শেষ হওয়া বার্তার পরে client error দেখা গেলে connection settings ভুল। তাই redis-cli ping-এ ফিরে যান।
Permission-এর কারণে কপি ব্যর্থ হলে ফাইলটি হাতে বসান এবং সেটির ownership 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.phpPlugin সরিয়ে ফেললে drop-in সরানো হয় না। আগে wp redis disable চালান। এটি Object cache disabled. মুদ্রণ করে এবং file-টি মুছে দেয়। Drop-in রেখে plugin directory মুছে ফেললে site পুরোনো cache code দিয়ে চলতে থাকে, কিন্তু সেটি update করার জন্য কোনো plugin থাকে না।
wp-config.php-এ সংযোগ সেটিংস
/* That's all, stop editing! */ লেখা লাইনটির উপরে এগুলো যোগ করুন, কারণ এর পরে সংজ্ঞায়িত constant কার্যকর করার জন্য দেরি হয়ে যায়।
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 এবং path নির্ধারণ করুন। এরপর 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 প্রতিটি key-এর জন্য seconds এককে expiry বাধ্যতামূলক করে। allkeys-lru ব্যবহার করলে এটি প্রয়োজন হয় না। তবে cached value সর্বোচ্চ কতটা পুরোনো হতে পারবে, তার একটি কঠোর সীমা নির্ধারণ করতে চাইলে এটি কার্যকর।
একটি Redis, একাধিক site: prefix ও database
Redis ডিফল্টভাবে 16টি numbered database দেয়, এবং প্রতিটির মধ্যে একটি flat keyspace থাকে। কোনো prefix ছাড়া database 0-এ নির্দেশ করা দুটি WordPress installation একই keyspace-এ একই key name লিখবে। ফলে একটি site অন্য site-এর option পড়ে সেগুলো পরিবেশন করতে পারে। প্রতিটি site-এর জন্য আলাদা prefix দিন।
define( 'WP_REDIS_PREFIX', 'shopA_prod:' );
define( 'WP_REDIS_DATABASE', 1 );Prefix key name আলাদা করে। Database index keyspace আলাদা করে। Flush করার সময় এটি গুরুত্বপূর্ণ: একটি index খালি করলে অন্য index-গুলো অপরিবর্তিত থাকে। Plugin-টি WP_REDIS_SELECTIVE_FLUSH-ও নথিভুক্ত করে। এটি পুরো database মুছে না দিয়ে শুধু আপনার prefix-এর সঙ্গে মেলা key মুছে দেয়। তবে সেগুলো খুঁজতে scan করতে হয়।
Prefix ও index memory আলাদা করে না। maxmemory এবং eviction policy পুরো instance-এর ওপর প্রযোজ্য। তাই একটি ব্যস্ত site কোনো শান্ত site-এর key সরিয়ে দিতে পারে, এবং কোনো site-ই তা জানায় না। যেসব site একে অপরকে প্রভাবিত করতে পারবে না, সেগুলোর জন্য আলাদা Redis instance ব্যবহার করুন। প্রতিটি instance-এর নিজস্ব socket এবং নিজস্ব limit থাকতে হবে।
Production-এর cache থেকে staging আলাদা রাখুন
সাধারণত staging site হলো production files এবং database-এর একটি কপি। তাই এটি একই prefix এবং একই database index-সহ wp-config.php-এর একটি কপি। এটিকে একই Redis-এর দিকে নির্দেশ করলে staging, staging-এর মান দিয়ে production-এর key লিখবে। ফলে কোনো deploy বা trace ছাড়াই একটি পরীক্ষামূলক price বা পরিবর্তিত option live site-এ দেখা যেতে পারে।
প্রতিটি environment-এর জন্য হাতে আলাদা salt নির্ধারণ করুন। staging-এর wp-config.php-এ:
define( 'WP_REDIS_PREFIX', 'shop_staging:' );
define( 'WP_REDIS_DATABASE', 5 );আরও ভালো হলো staging-এর জন্য আলাদা Redis instance ব্যবহার করা, অথবা কোনো object cache না রাখা। define( 'WP_REDIS_DISABLED', true ); runtime-এ cache বন্ধ করে এবং drop-in সক্রিয় রাখে। কোনো bug cache-এর কারণে হচ্ছে কি না, তা যাচাই করার এটিই দ্রুততম উপায়।
পুরোনো tutorial-গুলো এ জন্য WP_CACHE_KEY_SALT সেট করত। Plugin-এর readme-তে এই constant-কে deprecated এবং WP_REDIS_PREFIX দ্বারা প্রতিস্থাপিত বলা হয়েছে। তাই নতুন নামটি ব্যবহার করুন।
বিশ্বাস না করে যাচাই করুন
প্রথমে plugin-এর নিজস্ব diagnostics চালান।
wp redis statusসবচেয়ে গুরুত্বপূর্ণ লাইনটি হলো Drop-in। Drop-in: Valid-এর অর্থ, WordPress এই plugin-এর file load করছে। Drop-in: Not installed-এর অর্থ, copy কখনো হয়নি এবং site-এ কোনো persistent cache নেই—admin screen যতই সবুজ দেখাক না কেন। Status connection-এর অবস্থা জানায়, আর Client ব্যবহৃত extension-এর নাম দেখায়। এখানেই PhpRedis ব্যবহার হচ্ছে, Predis নয়, তা নিশ্চিত করুন।
এরপর সরাসরি WordPress core-কে জিজ্ঞাসা করুন, কারণ plugin কী মনে করছে, core তা বিবেচনা করে না।
wp eval 'var_dump( wp_using_ext_object_cache() );'bool(true)-এর অর্থ, core একটি external object cache-এর সঙ্গে যোগাযোগ করছে।
এরপর আপনার configured prefix ব্যবহার করে key আসছে কি না, তা প্রমাণ করুন।
redis-cli -n 0 dbsize
redis-cli -n 0 --scan --pattern 'shop_prod:*' | headSite-এ বিভিন্ন page খুলতে থাকলে dbsize-এর মান বাড়তে থাকা প্রমাণ হিসেবে কাজ করে। বৈধ drop-in থাকা সত্ত্বেও key-এর সংখ্যা 0 হলে connection নীরবে ব্যর্থ হচ্ছে, অথবা prefix আপনার ধারণার মতো নয়।
শেষে Redis আপনার জন্য কী পরিমাপ করছে, তা দেখুন।
redis-cli info stats | grep -E 'keyspace_hits|keyspace_misses|evicted_keys|expired_keys'Hit ratio হলো keyspace_hits / (keyspace_hits + keyspace_misses), এবং Redis-এর documentation-এ এই formula দেওয়া আছে। এটি পড়ার সময় দুটি বিষয় মনে রাখুন। Counter-গুলো শেষ restart-এর পর থেকে পুরো instance-এর হিসাব ধরে। তাই একই instance ব্যবহার করা প্রতিটি site ও application-এর হিসাব এতে একসঙ্গে মিশে থাকে। আর flush বা restart-এর ঠিক পরের ratio অর্থবহ নয়, কারণ তখন cache এখনও পূর্ণ হচ্ছে। একটি স্বাভাবিক traffic day পর্যন্ত এটি চলতে দিন।
কোনো hosting company প্রকাশিত hit rate বা query count-এর সঙ্গে আপনার সংখ্যার তুলনা করবেন না। সেগুলো তাদের site এবং তাদের plugin set-এর হিসাব। গুরুত্বপূর্ণ figure হলো আপনার নিজেরটি, যা page cache serve করতে পারে না এমন একটি page-এ আগে এবং পরে মেপেছেন।
curl -o /dev/null -s -w '%{time_starttransfer}\n' -b cookies.txt https://example.com/my-account/Logged-in cookie jar ব্যবহার করে এটি কয়েকবার চালান, প্রথমে cache বন্ধ রেখে (WP_REDIS_DISABLED), তারপর চালু রেখে। এই দুই ফলাফলের পার্থক্যই আপনার result।
Redis কখন WordPress ধীর করে
ভুল policy-সহ পূর্ণ instance-ই প্রধান কারণ। এটি উপরে আলোচনা করা হয়েছে: লগে OOM command not allowed when used memory > 'maxmemory'. দেখা যায়, এবং site-কে database ও cache—উভয়ের জন্য অর্থ দিতে হয়।
অন্য host-এ Redis রাখার বিষয়টি দ্বিতীয় কারণ। একটি request-এর মধ্যে WordPress শত শত object cache call করে। কোনো request-এ 500টি call হলে এবং প্রতিটি round trip-এ 1 ms খরচ হলে, local socket-এর তুলনায় অতিরিক্ত আধা সেকেন্ড অপেক্ষা করতে হয়। Redis একই box-এ রাখুন, অথবা sub-millisecond latency-সহ private network-এ রাখুন। একই box-এ kernel ব্যবহারের কারণে কতটা সুবিধা হয়, তা আলাদা বিষয়: Linux 7.2-এ যুক্ত cache-aware scheduling PHP-FPM এবং Redis-এর মতো ঘন ঘন পরস্পরের সঙ্গে যোগাযোগকারী process-কে একই cache share করা core-এ রাখার চেষ্টা করে। VPS guest bare metal-এর তুলনায় এই সুবিধা কম পায়।
অতিরিক্ত বড় autoloaded options table তৃতীয় কারণ, এবং পুরোনো site-এ এটি সাধারণ। WordPress সব autoloaded option একটি key হিসেবে cache করে। ফলে প্রতিটি request-এ connection-এর মাধ্যমে এক megabyte option পাঠানো হয়। এটি মাপুন:
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 value যোগ করেছে। তাই আধুনিক install-এ শুধু 'yes'-এর সঙ্গে মেলা পুরোনো query প্রকৃত পরিমাণের চেয়ে কম দেখায়। এক megabyte-এর বেশি হলে সমস্যা Redis-এ নয়, options table-এ ঠিক করতে হবে।
Restart করলে সবকিছু খালি হয়ে যায়। তাই systemctl restart redis-server-এর পরের কয়েক মিনিটে সব request cache miss হয় এবং সব database work আবার করতে হয়। Traffic কম থাকলে restart করুন। Object cache visitor page load-এর সময় wp-cron.php চলা বন্ধ করে না। এটিও slow request-এর একটি আলাদা উৎস: এই সুযোগে WP-Cron-কে প্রকৃত system cron job-এ সরিয়ে নিন।
পরিচ্ছন্নতা
অপশন বা theme code পরিবর্তন করে deploy করার পরে wp cache flush দিয়ে cache flush করুন। Plugin update-এর পরে drop-in নিজে আপডেট না হলে wp redis update-dropin চালান। পুরোনো plugin version-এর drop-in নতুন plugin version-এর সঙ্গে ব্যবহার করলে অস্বাভাবিক আচরণ হতে পারে। redis-cli --stat দিয়ে live server monitor করুন; এটি প্রতি সেকেন্ডে একটি করে লাইন দেখায়। redis-cli monitor প্রতিটি command দেখায় এবং ব্যস্ত instance-এ উল্লেখযোগ্য CPU ব্যবহার করে। তাই কোনো বিষয় পুনরুৎপাদন করার সময় এটি কয়েক সেকেন্ড চালিয়ে পরে বন্ধ করুন।
আরেকটি গুরুত্বপূর্ণ সংখ্যা হলো redis-cli info clients, যা connected_clients দেখায়। PHP-FPM প্রতিটি worker-এর জন্য একটি connection ধরে রাখে। তাই এই সংখ্যা আপনার pm.max_children-এর কাছাকাছি থাকা উচিত, মাত্রার দিক থেকে তার চেয়ে অনেক বেশি নয়। বেশি হলে কোনো process connection খুলে তা বন্ধ করছে না।
FAQ
Redis object cache চালালে কি এখনও page cache প্রয়োজন?
হ্যাঁ, anonymous traffic-এর জন্য। page cache সংরক্ষিত HTML পরিবেশন করে, PHP চালায় না। warm object cache থাকা অবস্থায়ও WordPress চালানোর চেয়ে এটি সবসময় কম ব্যয়বহুল। object cache সেই request-গুলো সামলায় যেগুলো page cache এড়িয়ে যায়: logged-in user, cart, checkout এবং wp-admin। shop বা membership site-এ দুটিই চালানো উপযোগী। যেসব site-এর visitor কখনও log in করে না, সেখানে প্রায় সব কাজ page cache-ই করে।
WordPress-এর জন্য Redis-কে কত memory দেওয়া উচিত?
অন্যের সংখ্যা অনুলিপি না করে নিজের server-এর হিসাব থেকে নির্ধারণ করুন। মোট RAM থেকে MySQL buffer pool এবং per-connection buffer বাদ দিন। এরপর একটি PHP-FPM worker-এর resident size দিয়ে pm.max_children গুণ করে সেটিও বাদ দিন। kernel ও web server-এর জন্য আরও কয়েকশ megabyte বাদ দিন। অবশিষ্ট memory-এর একটি অংশ Redis-কে দিন। তারপর এক দিন traffic চলার পরে redis-cli info memory-এ used_memory_human পরীক্ষা করে প্রয়োজন অনুযায়ী সমন্বয় করুন। একটি WordPress site সাধারণত কয়েক দশ megabyte-এ স্থির হয়। তাই 4 GB server-এ 256 MB maxmemory একটি উদার প্রাথমিক মান।
Redis object cache সক্রিয় করার পরে site ধীর হয়ে গেল কেন?
সাধারণ কারণ হলো noeviction policy ব্যবহার করা full instance। Redis নতুন write প্রত্যাখ্যান করে এবং OOM command not allowed when used memory > 'maxmemory'. ফেরত দেয়। ফলে WordPress প্রতিটি value-এর জন্য database-এ fallback করে এবং এর সঙ্গে অপ্রয়োজনীয় Redis round trip-এর খরচও যোগ হয়। redis-cli config get maxmemory-policy পরীক্ষা করুন, allkeys-lru সেট করুন, এবং maxmemory খুব ছোট নয় তা নিশ্চিত করুন। অন্য সাধারণ কারণ হলো remote host-এ থাকা Redis server। এতে প্রতিটি request-এ শত শত round trip-এর মোট latency বেড়ে যায়। আরেকটি কারণ হতে পারে বহু megabyte-এর autoloaded options value, যা প্রতিটি request-এ connection-এর মাধ্যমে পাঠানো হয়।
একাধিক WordPress site কি একই Redis server ব্যবহার করতে পারে?
সতর্কতার সঙ্গে পারে। প্রতিটি site-এর জন্য আলাদা WP_REDIS_PREFIX দিন, যাতে key name-এ সংঘর্ষ না হয়। প্রতিটি site-এর জন্য আলাদা WP_REDIS_DATABASE index ব্যবহার করুন, যাতে একটি site flush করলে অন্য site-এর data মুছে না যায়। তবে memory তারা এখনও ভাগ করে ব্যবহার করবে। maxmemory এবং eviction পুরো instance-এর ওপর প্রযোজ্য। তাই ব্যস্ত একটি site অন্য একটি কম সক্রিয় site-এর key evict করতে পারে। যেসব site একে অপরকে প্রভাবিত করতে পারবে না, সেগুলোর জন্য নিজস্ব limit-সহ আলাদা Redis instance প্রয়োজন।
wp-content/object-cache.php মুছে ফেলা কি নিরাপদ?
হ্যাঁ। এটি একটি drop-in; WordPress core-এর অংশ নয়। এটি সরিয়ে ফেললে WordPress-এর built-in per-request cache আবার ব্যবহৃত হয়। site সচল থাকে, তবে database query-এর সংখ্যা বাড়ে। wp redis disable ব্যবহার করাই ভালো। এটি file-টি পরিষ্কারভাবে মুছে এবং Object cache disabled. report করে। Redis বন্ধ থাকলে বা ত্রুটিপূর্ণ আচরণ করলে এবং admin-এ প্রবেশ করতে না পারলে হাতে file মুছে ফেলা উপযুক্ত জরুরি পদক্ষেপ।