VPS-এ WordPress-এর জন্য Redis Object Cache সেটআপ
নিজের VPS-এ Redis দিয়ে WordPress object cache চালু করুন: localhost-এ bind, maxmemory ও eviction policy নির্ধারণ, এবং cache সত্যিই কাজ করছে কি না যাচাই করুন।
WordPress-এর জন্য Redis object cache কী করে
WordPress-এর জন্য Redis object cache database query-এর ফলাফল memory-তে সংরক্ষণ করে। ফলে পরের request-এ 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 আর ব্যবহার করা হয় না। তখন WordPress পুরো request চালায়: bootstrap, plugins এবং queries। Object cache সেই request-এর খরচ কমায়। Page cache যে traffic সামলাতে পারে না, এর জন্য object cache ব্যবহার করা হয়: logged-in session, cart, checkout এবং wp-admin। WooCommerce shop-এ এই traffic-এর বেশির ভাগই ব্যয়বহুল।
দুটি cache একসঙ্গে ব্যবহার করা যায়। ব্যস্ত site-এ দুটিই প্রয়োজনীয়। আপনি কোন সমস্যার সমাধান করছেন, তা স্পষ্টভাবে নির্ধারণ করুন। Anonymous reader-সমৃদ্ধ একটি brochure site প্রায় পুরো speed 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 পরিবর্তন করুন। আপনার WordPress directory থেকে wp কমান্ডগুলো চালান। এই 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 দেখায়, তাহলে server চালু নেই। তাই এগিয়ে যাওয়ার আগে 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শেষের check-টি করার সময় সতর্ক থাকুন। php -m command line PHP-এর module-গুলো দেখায়। FPM ভিন্ন module set লোড করতে পারে। যে check-এর ফল নির্ভরযোগ্য, সেটি হলো 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 থাকে না। যে কোনো কিছু 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-এ service listening করছে তা পরীক্ষা করুন। কারণ configuration file শুধু একটি দাবি, আর ss হলো তার প্রমাণ।
sudo ss -lntp | grep 6379127.0.0.1:6379-ই প্রত্যাশিত ফল। 0.0.0.0:6379 দেখালে Redis public interface-এ সাড়া দিচ্ছে। bind লাইন ঠিক করে service restart করুন।
PHP এবং Redis একই মেশিনে থাকলে loopback TCP-এর চেয়ে Unix socket ভালো। এতে মাঝখানে TCP stack থাকে না। Access এমন firewall rule-এর ওপরও নির্ভর করে না, যা পরে পরিবর্তিত হয়ে যেতে পারে।
unixsocket /run/redis/redis-server.sock
unixsocketperm 770Socket-টির owner user এবং group হলো redis। তাই 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 start হওয়ার সময় যে group পেয়েছিল, সেটিই ধরে রাখে। তাই তালিকায় restart রাখা হয়েছে। Socket কাজ করছে নিশ্চিত না হওয়া পর্যন্ত TCP চালু রাখুন। নইলে একটি বানানভুলে দুই পথই একসঙ্গে বন্ধ হয়ে যেতে পারে।
Redis-কে কত মেমরি দেওয়া উচিত?
নিজের সার্ভারের তথ্য থেকে এই সংখ্যা নির্ধারণ করুন। কোনো maxmemory না থাকলে Redis বাড়তে থাকে, যতক্ষণ না kernel-এর মেমরি শেষ হয় এবং OOM killer একটি process বন্ধ করে দেয়। সাধারণত সবচেয়ে বড় process-টিই বন্ধ হয়। WordPress server-এ সেটি প্রায়ই MySQL। journalctl -k | grep -i "out of memory" পরে সেই বন্ধ হওয়ার ঘটনা দেখায়। ততক্ষণে site বন্ধ হয়ে যায়।
মোট 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 থেকে নেওয়া মাপ নয়। প্রতিটি সংখ্যা আপনার সার্ভারে প্রদর্শিত মান দিয়ে প্রতিস্থাপন করুন।
- 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 দিয়ে শুরু করা যুক্তিসঙ্গত। এতে যথেষ্ট headroom থাকে, এবং একটি WordPress site-এর সাধারণত এর বেশি প্রয়োজন হয় না।
এখন অনুমান না করে মাপ নিন। এক দিন প্রকৃত network traffic চলার পর:
redis-cli info memory | grep -E 'used_memory_human|maxmemory_human|maxmemory_policy'
redis-cli dbsizeused_memory_human যদি আপনার limit-এর তুলনায় অনেক কম থাকে, limit কমিয়ে RAM MySQL-কে দিন। MySQL এই RAM আরও কার্যকরভাবে ব্যবহার করবে। used_memory_human যদি limit-এ স্থির থাকে এবং evicted_keys সারা দিন বাড়তে থাকে, limit বাড়ান। মানটি /etc/redis/redis.conf-এ সেট করুন।
maxmemory 256mb
maxmemory-policy allkeys-lruredis-cli config set maxmemory 256mb এখনই প্রয়োগ হয়, কিন্তু পরবর্তী restart-এ হারিয়ে যায়। এটি bare sysctl -w ব্যবহারের একই সমস্যা। File সম্পাদনা করুন, তারপর sudo systemctl restart redis-server চালান, এবং শেষে মানটি আবার পড়ে যাচাই করুন। আরও একটি সীমা রাখা ভালো: systemd unit-এ MemoryMax cap misconfigured Redis-কে পুরো server অচল করে দিতে বাধা দেয়। এটি maxmemory-এর চেয়ে বেশি সেট করুন, কখনোই সমান নয়। কারণ cgroup limit key evict না করে process বন্ধ করে দেয়। WordPress-এর পাশে Redis container-এ চললে একই সংখ্যা আপনার Compose file-এর memory limits-এ দিতে হবে। একই যুক্তি database Docker-এ চালানো নাকি host-এ চালানো বেছে নেওয়ার ক্ষেত্রেও প্রযোজ্য।
ইচ্ছাকৃতভাবে eviction policy নির্বাচন করুন
নতুন Redis-এর default হলো noeviction। আপনার সেটিং পরীক্ষা করুন:
redis-cli config get maxmemory-policynoeviction ব্যবহার করলে instance-এর memory পূর্ণ হয়ে গেলে সেটি আর write গ্রহণ করে না এবং এই বার্তাটি দেখায়:
(error) OOM command not allowed when used memory > 'maxmemory'.এই guide-এ এটি সবচেয়ে খারাপ 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 দিয়ে grep করুন।
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 তৈরি করে না।
ব্যর্থতার message-গুলো দেখায় কোন অংশে সমস্যা হয়েছে। 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: দিয়ে শেষ হওয়া message-এর পরে client error দেখা গেলে connection settings ভুল। সে ক্ষেত্রে 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.phpPlugin সরিয়ে ফেললেও drop-in সরানো হয় না। প্রথমে wp redis disable চালান। এটি Object cache disabled. প্রিন্ট করে এবং ফাইলটি মুছে দেয়। Drop-in রেখে plugin directory মুছে ফেললে সাইটটি পুরোনো cache code চালাতে থাকে, কিন্তু সেটি update করার জন্য কোনো plugin থাকে না।
wp-config.php-এ connection settings
/* 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-এর জন্য সেকেন্ডে expiry বাধ্যতামূলক করে। allkeys-lru ব্যবহার করলে এটি প্রয়োজন হয় না। তবে cached value কতটা পুরোনো হতে পারবে, তার একটি কঠোর সর্বোচ্চ সীমা নির্ধারণ করতে চাইলে এটি উপযোগী।
একটি Redis, একাধিক site: prefix ও database
Redis ডিফল্টভাবে 16টি নম্বরযুক্ত database দেয়, এবং প্রতিটির ভিতরে একটি flat keyspace থাকে। prefix ছাড়া database 0-এ নির্দেশ করা দুটি WordPress install একই 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 file ও database-এর একটি copy। তাই এটি wp-config.php-এরও copy এবং একই prefix ও একই database index ব্যবহার করে। এটিকে একই Redis-এর দিকে নির্দেশ করলে staging, production-এর key-তে staging-এর value লিখবে। এরপর test price বা পরিবর্তিত কোনো option কোনো deploy ছাড়াই এবং কোনো trace না রেখেই 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-এ click করার সময় dbsize বাড়তে থাকা প্রমাণটি দেয়। Valid 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-এর data এতে মিশে থাকে। আর flush বা restart-এর ঠিক পরের ratio অর্থপূর্ণ নয়, কারণ তখনও cache পূরণ হচ্ছে। স্বাভাবিক traffic-এর একটি দিন পার হতে দিন।
Hosting company প্রকাশিত hit rate বা query count-এর সঙ্গে আপনার সংখ্যাটি তুলনা করবেন না। সেগুলো তাদের site এবং তাদের plugin set-এর হিসাব। গুরুত্বপূর্ণ সংখ্যা হলো আপনার নিজের সংখ্যা, যা 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), তারপর cache চালু রেখে। এই পার্থক্যটিই আপনার ফলাফল।
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-এ রাখুন।
একটি বড় autoloaded options table তৃতীয় সমস্যা। পুরোনো site-এ এটি সাধারণ। WordPress সব autoloaded option-কে একটি key হিসেবে cache করে। তাই প্রতিটি request-এ এক megabyte option connection-এর মধ্য দিয়ে যায়। পরিমাপ করুন:
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 miss হয় এবং সব database কাজ আবার সম্পন্ন হয়। Traffic কম থাকলে restart করুন। Object cache visitor page load-এর সময় wp-cron.php চালানো বন্ধ করে না। এটিও ধীর 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-এর সঙ্গে ব্যবহার করলে অস্বাভাবিক আচরণ হতে পারে। redis-cli --stat দিয়ে live server monitor করুন; এটি প্রতি সেকেন্ডে একটি করে line দেখায়। 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 PHP না চালিয়ে সংরক্ষিত HTML সরবরাহ করে, তাই warm object cache থাকা WordPress চালানোর চেয়ে এর খরচ সবসময় কম। page cache যেসব request বাদ দেয়, object 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 এবং প্রতি-connection buffer বাদ দিন। এরপর pm.max_children-কে একটি PHP-FPM worker-এর resident size দিয়ে গুণ করে সেই পরিমাণ বাদ দিন। 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-এর সময় যোগ হয়, এবং কয়েক megabyte-এর autoloaded options value, যা প্রতিটি request-এ connection-এর মাধ্যমে পাঠানো হয়।
একাধিক WordPress site কি একটি Redis server ভাগ করে ব্যবহার করতে পারে?
সতর্কতার সঙ্গে ব্যবহার করতে পারে। প্রতিটি site-কে আলাদা WP_REDIS_PREFIX দিন, যাতে key name-এ সংঘর্ষ না হয়। একটি site flush করলে অন্য site-এর key মুছে না যায়, সে জন্য আলাদা WP_REDIS_DATABASE index ব্যবহার করুন। তবে তারা 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 down বা অস্বাভাবিক আচরণ করলে এবং admin-এ পৌঁছাতে না পারলে হাতে file মুছে ফেলা যথাযথ জরুরি পদক্ষেপ।