کش دولایه با Redis و Nginx برای عبور از ترافیک ناگهانی کمپینها
چطور با میکروکش Nginx و کش داده در Redis، یک فروشگاه را در برابر ترافیک ناگهانی کمپینها مقاوم کنیم بدون اینکه قیمت و سبد خرید کاربر اشتباه نمایش داده شود.
وقتی یک کمپین تبلیغاتی یا استوری پربازدید منتشر میشود، در چند دقیقه چند برابر ترافیک عادی به سایت میرسد. اگر هر درخواست به دیتابیس برسد، سرور زودتر از کمپین تمام میشود. کش دولایه این فشار را جذب میکند.
لایه اول: میکروکش Nginx برای صفحات عمومی
صفحاتی که برای همه کاربران یکساناند (لیست محصولات، صفحه دسته، مقالات) میتوانند برای چند ثانیه در Nginx کش شوند. حتی کش یکثانیهای یعنی در اوج ترافیک، فقط یک درخواست در ثانیه به اپلیکیشن میرسد. نکته کلیدی: هر درخواستی که کوکی نشست دارد باید از کش عبور کند.
proxy_cache_path /var/cache/nginx/micro levels=1:2
keys_zone=micro:20m max_size=500m inactive=10m;
map $http_cookie $skip_cache {
default 0;
~*session= 1; # کاربر لاگینشده یا دارای سبد خرید
}
location / {
proxy_cache micro;
proxy_cache_valid 200 5s;
proxy_cache_use_stale updating error timeout;
proxy_cache_lock on;
proxy_cache_bypass $skip_cache;
proxy_no_cache $skip_cache;
proxy_pass http://127.0.0.1:3000;
}نکات کلیدی
- proxy_cache_lock جلوی هجوم همزمان درخواستها به اپ را میگیرد.
- proxy_cache_use_stale updating یعنی در زمان بروزرسانی، نسخه قبلی سرو شود.
- صفحات سبد خرید، پرداخت و پنل کاربری هرگز کش نمیشوند.
لایه دوم: کش داده در Redis
کوئریهای سنگین و پرتکرار (درخت دستهبندی، تنظیمات سایت، لیست برندها) در Redis با زمان انقضا نگهداری میشوند. هنگام تغییر داده در پنل مدیریت، کلید مربوط حذف میشود تا داده کهنه نمایش داده نشود.
async function cached<T>(key: string, ttlSec: number, load: () => Promise<T>): Promise<T> {
const hit = await redis.get(key);
if (hit) return JSON.parse(hit) as T;
const value = await load();
await redis.set(key, JSON.stringify(value), 'EX', ttlSec);
return value;
}
// هنگام ویرایش در پنل:
await redis.del('categories:tree');جمعبندی
کش خوب یعنی بدانید چه چیزی را نباید کش کنید. قیمت، موجودی لحظهای و هر چیزی که به کاربر وابسته است بیرون از کش میماند؛ بقیه میتواند چند ثانیه کهنه باشد و سایت را زنده نگه دارد.