کش Redis برای سایت؛ پنج اشتباه که به جای سرعت، دردسر می آورد
کش Redis برای سایت وقتی سرعت می ده که انقضا، نام گذاری کلیدها و داده های حساس رو درست مدیریت کرده باشی. پنج اشتباه رایج رو با پیامد و راه درستشون مرور می کنیم.

کش Redis برای سایت وقتی سرعت می ده که سه چیز رو درست تنظیم کرده باشی: زمان انقضای هر کلید، نام گذاری قابل پیش بینی کلیدها و کنار گذاشتن داده های حساس از کش. اگه یکی از این سه تا غلط باشه، سایتت به جای سریع تر شدن، قدیمی یا کند یا حتی ناامن می شه. پنج اشتباه رایج رو با پیامد و راه درستشون مرور می کنیم.
کش Redis برای سایت؛ فرض کن حراج شب یلدا شروع شده
فرض کن یه فروشگاه آنلاین برای شب یلدا حراج گذاشته. مدیر قیمت یه کالا رو عوض کرده، ولی مشتری هنوز قیمت قدیمی رو می بینه و تو صفحه پرداخت با عدد دیگه ای روبرو می شه. یا بدتر: کلیدهای صفحه محصول دقیقاً همزمان منقضی می شن و کل ترافیک اوج شب یه دفعه می ریزه روی دیتابیس.
تقصیر این اتفاق ها با Redis نیست، از تنظیم و طراحی خودمونه. یه نکته صادقانه هم بگم: کش همیشه جواب نیست. اگه صفحه ات کنده چون یه کوئری ایندکس نداره، اول برو سراغ کوئری کند در MySQL؛ از slow query log تا ایندکس درست. کش روی کوئری خراب مثل رنگ کردن دیوار نم کشیده می مونه.
اشتباه اول: کلیدی که هیچ وقت تاریخ انقضا نداره
کش رو مثل یخچال دفتر تصور کن. غذایی که تاریخ نداره و کسی نمی دونه مال کیه، یا می پوسه (داده قدیمی) یا کم کم یخچال رو پر می کنه (حافظه پر). کلید بدون TTL دقیقاً همین حالته. معمولاً با این فکر ذخیره می شه که «بعداً پاکش می کنیم»، و اون «بعداً» هیچ وقت نمی رسه.
حافظه سرور آروم آروم پر می شه، کاربر داده قدیمی می بینه و در بدترین حالت RAM تموم می شه و سرویس می خوابه. روی سرور مجازی با حافظه کم این اتفاق زودتر می افته.
برای همه کلیدهای کش یه TTL پیش فرض بذار و سقف حافظه Redis رو هم مشخص کن تا وقتی حافظه پر شد، Redis خودش سراغ کلیدهایی بره که کمتر استفاده شدن:
maxmemory 256mb
maxmemory-policy allkeys-lru
عدد رو با حافظه سرور خودت هماهنگ کن و نام سیاست ها رو با مستندات نسخه ای که نصب کردی تطبیق بده. بعدش برای هر نوع داده، انقضای متناسب انتخاب کن:
| نوع داده | بازه تقریبی انقضا | دلیل |
|---|---|---|
| قیمت و موجودی | چند ثانیه تا چند دقیقه | مستقیم به سفارش و پرداخت وصله |
| لیست پرفروش ها و نتیجه جستجو | حدود چند دقیقه | کمی کهنگی قابل تحمله |
| منو و دسته بندی | حدود چند ساعت تا یک روز | کم تغییر می کنه |
این بازه ها فقط نقطه شروعن، نه قانون. معیار اصلی اینه که اگه کاربر نسخه کهنه رو ببینه، چه ضرری می بینه.
اشتباه دوم: همه کلیدها با هم می میرن
اگه همه کلیدها رو تو یه لحظه و با یه TTL ثابت ساخته باشی، همه با هم منقضی می شن. مثل اینه که غذای تمام یخچال همزمان خراب بشه. کش خالی می شه، صدها درخواست همزمان می بینن جواب تو کش نیست و همه می رن سراغ دیتابیس. به این وضع می گن cache stampede.
ساعت های اوج، مثل شب حراج، دیتابیس زیر این فشار ناگهانی کند می شه یا از کار می افته. اگه دیتابیس روی همون سرور سایته و منابعش محدوده، زودتر هم حسش می کنی. سه کار کنار هم جواب می ده:
- به TTL یه مقدار تصادفی کوچک اضافه کن تا انقضاها پخش بشن (jitter).
- برای کلیدهای پرترافیک، فقط یه درخواست اجازه داشته باشه کش رو بازسازی کنه و بقیه صبر کنن یا نسخه قبلی رو بگیرن.
- قبل از اوج ترافیک، صفحه های مهم رو از قبل گرم کن.
بده بستانش رو هم بدون: قفل و بازسازی در پس زمینه کد رو پیچیده تر می کنن. اگه ترافیکت متوسطه، jitter به تنهایی معمولاً کافیه.

اشتباه سوم: اسم کلیدها رو بی فکر نذار
کلیدهایی مثل product، list یا data1 تا وقتی پروژه کوچیکه مشکلی نمی سازن. ولی به محض اینکه یه سرور Redis بین چند سایت یا چند بخش مشترک بشه، یا زبان و واحد پول اضافه بشه، کلیدها روی هم می افتن. اون موقع صفحه فارسی با محتوای انگلیسی نمایش داده می شه، قیمت ریالی جای تومانی می شینه و بدتر از همه، سبد خرید یه کاربر می تونه به کاربر دیگه ای نشون داده بشه، چون شناسه کاربر تو کلید نبوده.
الگوی ثابت و خوانایی انتخاب کن که هر چیزی که خروجی رو عوض می کنه توش باشه:
shop:v3:product:1042:fa:toman
اینجا shop اسم پروژه، v3 نسخه ساختار داده، بعدش نوع و شناسه و آخر هم زبان و واحد پول اومده. وقتی ساختار داده عوض شد، فقط نسخه رو بالا می بری و کلیدهای قدیمی (اگه TTL داشته باشن) خودشون منقضی می شن. برای پاک کردن گروهی رو سرور واقعی از SCAN استفاده کن، نه KEYS؛ چون KEYS روی کلیدهای زیاد، Redis رو برای مدتی بلاک می کنه.
اشتباه چهارم: هر چیزی رو تو کش نریز
وسوسه انگیزه که هر چی کند بود رو کش کنی: پروفایل کاربر، توکن نشست، حتی کد تایید پیامکی. ولی Redis پیش فرض رمز نداره، و اگه یه تنظیم اشتباه پورتش رو باز بذاره، هر چی داخلشه قابل خوندنه. تو ایران هم اگه اطلاعات پرداخت یا هویت کاربر لو بره، پاسخگوییش با خودته و ممکنه با درگاه پرداخت هم دردسر پیدا کنی؛ الزامات درگاهت رو از خودش بپرس.
- رمز و اطلاعات کارت رو اصلاً کش نکن. کد تایید و توکن رو هم اگه ناچاری تو Redis نگه می داری، با TTL خیلی کوتاه و ترجیحاً هش شده نگه دار.
- صفحه ای که برای کاربر لاگین کرده ساخته شده رو با کش عمومی صفحه قاطی نکن. اگه کوکی نشست داره، کلید حتماً باید شناسه کاربر داشته باشه یا اصلاً کش نشه.
- Redis رو فقط روی
localhostیا شبکه خصوصی در دسترس بذار (bind)، رمز یا ACL فعال کن و پورتش رو با فایروال ببند.
اگه مطمئن نیستی تنظیمات سرورت امنه، مدیریت و امن سازی سرور دقیقاً برای همین جور بازبینی هاست. کد پیامکی هم بحث جداگانه داره که تو ورود با کد پیامکی در سایت و اپلیکیشن؛ چهار تصمیم پیش از پیاده سازی بررسی کردیم.
اشتباه پنجم: کش رو جای دیتابیس نگیر
کش قراره سریع باشه، نه قابل اعتماد. Redis ممکنه ری استارت بشه، حافظه اش پر بشه و کلیدها رو حذف کنه، یا اصلاً در دسترس نباشه. هر چیزی که از دست دادنش برات مشکل می سازه، جاش اونجا نیست. اگه شمارنده ها با ری استارت صفر بشن، محدودیت ها دور زده می شن. و اگه کد سایت فرض کنه «Redis همیشه هست»، با اولین قطعی صفحه خطای ۵۰۰ می ده.
داده هایی که نباید گم بشن، تو دیتابیس بمونن. مثلاً محدودیت ارسال کد ورود برای هر موبایل و هر IP رو تو پایگاه داده بشمار، نه تو حافظه، تا با ری استارت از بین نره.
قطعی کش باید قابل تحمل و قابل دیدن باشه. درخواست به Redis timeout کوتاه داشته باشه و در صورت خطا، سایت از دیتابیس بخونه؛ کندتر ولی زنده.
یه هشدار: مسیر جایگزین به دیتابیس تو اوج ترافیک می تونه خودش مشکل بسازه، پس مانیتورینگ حافظه و تعداد خطاهای Redis رو جدی بگیر. اگه کارهای سنگین پس زمینه داری، صف کار در بک اند چیست و چه وقت به آن نیاز پیدا می کنیم؟ بهتر از کش به دردت می خوره.

سوالات متداول
کش Redis برای هر سایتی لازمه؟
نه. اگه ترافیکت کمه و کوئری هات سریعن، شاید کش فقط پیچیدگی اضافه کنه. اول ایندکس ها و کوئری های کند رو درست کن، بعد ببین واقعاً به کش نیاز داری یا نه.
TTL مناسب برای کش چقدره؟
عدد جادویی نداره. هر چی ضرر نمایش داده قدیمی بیشتره، TTL کوتاه تر باشه: قیمت و موجودی چند ثانیه تا چند دقیقه، منو و دسته بندی چند ساعت یا بیشتر.
داده کاربر لاگین شده رو می شه کش کرد؟
می شه، ولی با شرط. شناسه کاربر باید تو کلید باشه، TTL کوتاه باشه و هیچ وقت صفحه شخصی با کش عمومی قاطی نشه. رمز و داده پرداخت رو کش نکن.
اگه Redis از کار بیفته، سایت هم می خوابه؟
نباید بخوابه. کد باید با timeout کوتاه به Redis وصل بشه و در صورت خطا از دیتابیس بخونه. فقط حواست باشه دیتابیس تو ساعت های اوج می تونه زیر فشار بره.
قبل از اولین دیپلوی این چند چیز رو چک کن
هر کلید TTL داره و حافظه سقف داره؟ انقضاها پخش شدن؟ کلیدها الگوی ثابت، نسخه و شناسه کاربر دارن؟ چیز حساسی تو کش نیست و پورت Redis بسته شده؟ و اگه تو محیط تست Redis رو خاموش کنی، سایت هنوز کار می کنه؟ اگه جواب همه اینا آره بود، بهینه سازی سرعت از جایی شروع می شه که کش کمک می کنه، نه دردسر می سازه.


