Caching در Frontend دقیقاً کجا اتفاق میافتد؟ Browser، CDN، Server و Application
وقتی درباره سرعت یک وبسایت صحبت میکنیم، یکی از اولین مفاهیمی که مطرح میشود Caching است.
اما یک سؤال مهم وجود دارد:
داده دقیقاً کجا Cache میشود؟
آیا داخل مرورگر کاربر ذخیره میشود؟
آیا CDN آن را نگه میدارد؟
آیا Server پاسخها را Cache میکند؟
یا خود Application دادهها را در حافظه یا Redis نگه میدارد؟
پاسخ این است که Caching فقط در یک نقطه اتفاق نمیافتد.
در یک معماری مدرن، ممکن است یک درخواست از چندین لایه Cache عبور کند:
User
↓
Browser Cache
↓
CDN Cache
↓
Server Cache
↓
Application Cache
↓
Database
هرکدام از این لایهها هدف متفاوتی دارند و در زمان متفاوتی وارد عمل میشوند.
درک درست این معماری به ما کمک میکند سایتهایی سریعتر، مقیاسپذیرتر و کمهزینهتر طراحی کنیم.
Caching چیست؟
Caching یعنی ذخیره موقت داده یا نتیجه یک عملیات پرهزینه، تا در درخواستهای بعدی بتوانیم آن را سریعتر در اختیار کاربر قرار دهیم.
فرض کنید کاربر صفحهای را درخواست میکند:
GET /products
بدون Cache ممکن است مسیر زیر طی شود:
Browser
↓
Server
↓
Application
↓
Database
↓
Application
↓
Server
↓
Browser
اگر این درخواست بارها تکرار شود، انجام دوباره تمام این مراحل منطقی نیست.
در اینجا Cache وارد میشود.
مثلاً:
Request
↓
Cache Hit
↓
Cached Response
در این حالت نیازی نیست هر بار تمام عملیات از ابتدا انجام شود.
چرا Caching اهمیت دارد؟
Caching میتواند چند مزیت مهم ایجاد کند:
کاهش زمان پاسخ
کاهش درخواست به Server
کاهش فشار روی Database
کاهش مصرف منابع
کاهش حجم داده منتقلشده
افزایش ظرفیت سیستم
بهبود تجربه کاربر
کاهش هزینه زیرساخت
اما مهمترین نکته این است که همه Cacheها یکسان نیستند.
برای مثال Browser Cache با CDN Cache تفاوت دارد و Application Cache نیز منطق کاملاً متفاوتی دارد.
۱. Browser Cache؛ نزدیکترین Cache به کاربر
اولین لایهای که معمولاً با آن مواجه میشویم، Browser Cache است.
مرورگر میتواند برخی منابع سایت را روی دستگاه کاربر ذخیره کند.
برای مثال:
HTML
CSS
JavaScript
Images
Fonts
اگر کاربر دوباره به همان سایت مراجعه کند، مرورگر ممکن است به جای دریافت دوباره فایلها از شبکه، نسخه ذخیرهشده را استفاده کند.
Browser Cache چگونه کار میکند؟
یکی از مهمترین ابزارهای کنترل Browser Cache، HTTP Headerها هستند.
مثلاً Server میتواند چنین Headerای ارسال کند:
Cache-Control: public, max-age=3600
این Header به مرورگر میگوید که منبع مورد نظر میتواند برای مدت مشخصی Cache شود.
برای Assets استاتیک معمولاً سیاست Cache میتواند بسیار طولانیتر باشد.
مثلاً:
Cache-Control: public, max-age=31536000, immutable
البته استفاده از Cache طولانی برای فایلهایی که نامشان ثابت میماند، نیازمند مدیریت درست Versioning است.
چرا Versioning در Browser Cache مهم است؟
فرض کنید فایل شما این نام را دارد:
app.js
مرورگر نسخه قدیمی آن را Cache کرده است.
حالا شما کد جدیدی منتشر میکنید، اما نام فایل همچنان:
app.js
است.
ممکن است مرورگر همچنان نسخه قدیمی را استفاده کند.
یکی از راهحلهای رایج، Hash کردن نام فایل است:
app.83fd21.js
پس از تغییر محتوا:
app.9a721c.js
در این حالت مرورگر متوجه میشود که فایل جدید است و باید آن را دریافت کند.
این تکنیک را معمولاً Cache Busting مینامیم.
۲. CDN Cache؛ Cache نزدیک به کاربر
لایه بعدی CDN است.
CDN یا Content Delivery Network شبکهای از سرورها در نقاط مختلف جغرافیایی است.
به جای اینکه تمام کاربران مستقیماً به Origin Server متصل شوند، محتوا میتواند در Edge Serverهای مختلف ذخیره شود.
برای مثال:
User
↓
CDN Edge
↓
Origin Server
اگر محتوای مورد نظر قبلاً در CDN ذخیره شده باشد، ممکن است درخواست اصلاً به Origin نرسد.
CDN Cache چه چیزی را ذخیره میکند؟
CDN میتواند برای موارد مختلفی استفاده شود، از جمله:
تصاویر
فایلهای CSS
فایلهای JavaScript
فونتها
فایلهای ویدئویی
صفحات HTML
پاسخهای API در شرایط مناسب
البته اینکه چه چیزی Cache شود به معماری سیستم و سیاست Cache بستگی دارد.
Cache Hit و Cache Miss چیست؟
در سیستمهای Cache معمولاً با دو مفهوم مهم مواجه میشویم.
Cache Hit
داده مورد نظر در Cache وجود دارد.
Request
↓
Cache
↓
FOUND
↓
Response
در این حالت نیازی نیست درخواست تا Origin Server ادامه پیدا کند.
Cache Miss
داده در Cache وجود ندارد.
Request
↓
Cache
↓
NOT FOUND
↓
Origin Server
↓
Response
در بسیاری از سیستمها، پس از دریافت پاسخ از Origin، داده برای درخواستهای بعدی Cache میشود.
۳. Server Cache؛ Cache در سمت سرور
بعد از CDN به لایه Server میرسیم.
ممکن است CDN پاسخ خاصی را Cache نکرده باشد، اما Server یا زیرساخت Backend بتواند بخشی از دادهها را Cache کند.
برای مثال:
Server
↓
Cache
↓
Database
در این حالت اگر داده در Cache موجود باشد، نیازی به Query دوباره Database نیست.
Server Cache چه چیزی را ذخیره میکند؟
بسته به معماری، میتوان مواردی مانند:
HTML تولیدشده
نتیجه Query
Session Data
API Response
Configuration
دادههای موقت
را Cache کرد.
یکی از ابزارهای رایج برای این نوع Cache، Redis است.
برای مثال:
Request
↓
Server
↓
Redis
↓
Cached Data
اگر داده موجود نباشد:
Request
↓
Server
↓
Redis → Miss
↓
Database
↓
Redis ← Store
↓
Response
۴. Application Cache؛ Cache داخل منطق برنامه
یکی از مهمترین و در عین حال متفاوتترین لایهها، Application Cache است.
در اینجا Cache بخشی از منطق خود Application است.
مثلاً فرض کنید یک API برای دریافت اطلاعات محصولات داریم:
GET /api/products
Application میتواند نتیجه این درخواست را برای چند دقیقه ذخیره کند.
مثلاً:
products
TTL: 300 seconds
در درخواستهای بعدی:
API Request
↓
Application Cache
↓
Cached Products
به جای اینکه هر بار Database Query شود، Application میتواند نتیجه Cacheشده را برگرداند.
Application Cache چه تفاوتی با Browser Cache دارد؟
تفاوت اصلی در محل و مسئولیت Cache است.
Browser Cache در سمت کاربر قرار دارد:
User Device
└── Browser Cache
اما Application Cache در سمت Backend قرار دارد:
Server
└── Application
└── Cache
بنابراین Browser Cache معمولاً برای کاهش درخواستهای شبکه و دریافت مجدد منابع استفاده میشود، در حالی که Application Cache بیشتر برای کاهش هزینه پردازش داخلی Application به کار میرود.
یک درخواست میتواند از چند Cache عبور کند
حالا تصور کنیم کاربر یک صفحه را درخواست میکند.
ممکن است معماری چیزی شبیه این باشد:
┌───────────────┐
│ Browser Cache │
└───────┬───────┘
│ Miss
↓
┌───────────────┐
│ CDN Cache │
└───────┬───────┘
│ Miss
↓
┌───────────────┐
│ Server Cache │
└───────┬───────┘
│ Miss
↓
┌───────────────┐
│ Application │
│ Cache │
└───────┬───────┘
│ Miss
↓
┌───────────────┐
│ Database │
└───────────────┘
هرچه درخواست در لایههای بالاتری پاسخ داده شود، معمولاً هزینه رسیدن به داده اصلی کمتر خواهد بود.
تفاوت چهار لایه Cache در یک نگاه
لایهمحلهدف اصلیBrowser Cacheدستگاه کاربرجلوگیری از دانلود مجددCDN CacheEdge Serverارائه محتوا از نزدیکترین نقطهServer CacheBackend/Serverکاهش پردازش و درخواستهای تکراریApplication Cacheمنطق Applicationجلوگیری از اجرای مجدد عملیات پرهزینه
نکته مهم این است که این لایهها جایگزین یکدیگر نیستند.
یک معماری حرفهای ممکن است از همه آنها به صورت همزمان استفاده کند.
Cache-Control؛ زبان کنترل HTTP Cache
یکی از مهمترین ابزارها برای مدیریت Cache، Header زیر است:
Cache-Control
برای مثال:
Cache-Control: public, max-age=3600
یعنی Response میتواند برای یک ساعت Cache شود.
یا:
Cache-Control: no-store
یعنی Response نباید ذخیره شود.
همچنین:
Cache-Control: private
برای دادههایی که نباید توسط Cacheهای عمومی مانند CDN ذخیره شوند، کاربرد دارد.
ETag چیست؟
یکی دیگر از مفاهیم مهم، ETag است.
فرض کنید مرورگر نسخهای از یک فایل را دارد.
به جای اینکه همیشه فایل را کامل دانلود کند، میتواند از Server بپرسد:
آیا این فایل تغییر کرده است؟
Server ممکن است ETag قبلی را بررسی کند.
مثلاً:
If-None-Match: "abc123"
اگر فایل تغییر نکرده باشد، Server میتواند پاسخ دهد:
304 Not Modified
در این حالت مرورگر میتواند از نسخه Cacheشده خودش استفاده کند.
این روش باعث میشود انتقال داده غیرضروری کاهش پیدا کند.
Cache Invalidation؛ سختترین بخش Caching
یکی از معروفترین مشکلات سیستمهای Cache این است:
چه زمانی باید Cache را پاک یا بهروزرسانی کنیم؟
فرض کنید اطلاعات محصول تغییر کرده است.
اما Cache هنوز نسخه قبلی را دارد.
در این حالت کاربر ممکن است اطلاعات قدیمی ببیند.
به این مسئله Cache Invalidation میگوییم.
روشهای مختلفی برای حل آن وجود دارد:
TTL
Invalidation
Revalidation
Versioning
Cache Busting
Tag-based Invalidation
انتخاب روش مناسب به نوع داده بستگی دارد.
TTL چیست؟
TTL یا Time To Live مشخص میکند داده چه مدت در Cache معتبر باشد.
مثلاً:
TTL = 300 seconds
یعنی داده میتواند برای ۵ دقیقه معتبر باشد.
بعد از آن سیستم میتواند داده جدید را دریافت کند.
برای دادههایی که مرتب تغییر نمیکنند:
TTL طولانیتر
و برای دادههای حساس و سریعالتغییر:
TTL کوتاهتر
معمولاً انتخاب مناسبتری است.
آیا همه چیز باید Cache شود؟
خیر.
این یکی از مهمترین نکات طراحی سیستمهای Cache است.
برای دادههایی که:
دائماً تغییر میکنند
شخصی هستند
حساس هستند
نباید نسخه قدیمی آنها نمایش داده شود
باید سیاست Cache با دقت بیشتری انتخاب شود.
برای مثال اطلاعات عمومی یک صفحه محصول ممکن است گزینه خوبی برای Cache باشد.
اما اطلاعات شخصی حساب کاربر معمولاً نیازمند سیاست متفاوتی است.
Caching در APIها
APIها یکی از مهمترین بخشهایی هستند که میتوانند از Cache استفاده کنند.
فرض کنید:
GET /api/categories
دستهبندیها ممکن است در طول روز چند بار بیشتر تغییر نکنند.
در نتیجه میتوان آنها را Cache کرد.
اما API زیر:
GET /api/user/account
ممکن است دادهای شخصی و حساس برگرداند و نباید مانند یک محتوای عمومی Cache شود.
بنابراین Cache Strategy باید بر اساس نوع داده طراحی شود، نه صرفاً نوع Endpoint.
Caching در Frontend فقط Browser Cache نیست
گاهی وقتی میگوییم:
«Frontend را Cache کنیم»
منظور فقط Cache کردن فایلهای JavaScript یا تصاویر در Browser نیست.
Frontend مدرن با تمام لایههای معماری ارتباط دارد:
Browser
↓
CDN
↓
Server
↓
Application
↓
Database
و هر لایه میتواند استراتژی Cache مخصوص خودش را داشته باشد.
به همین دلیل Performance واقعی معمولاً نتیجه همکاری چند لایه است، نه یک تکنیک واحد.
Caching و Performance
اگر یک درخواست بدون Cache چنین مسیری داشته باشد:
Browser
↓
Network
↓
Server
↓
Application
↓
Database
↓
Application
↓
Server
↓
Network
↓
Browser
اما با Cache در CDN:
Browser
↓
Network
↓
CDN
↓
Response
طبیعی است که مسیر دوم در بسیاری از شرایط سریعتر باشد.
اگر حتی Browser Cache هم Hit شود:
Browser
↓
Cached Response
دیگر حتی درخواست شبکه نیز ممکن است لازم نباشد.
مشکل اصلی Caching چیست؟
Caching سرعت را افزایش میدهد، اما پیچیدگی سیستم را نیز بالا میبرد.
هرچه Cache بیشتری داشته باشیم، باید موارد بیشتری را مدیریت کنیم:
چه چیزی Cache شود؟
کجا Cache شود؟
چه مدت Cache شود؟
چه زمانی منقضی شود؟
چگونه Invalidate شود؟
چه کسی نسخه جدید را دریافت کند؟
بنابراین:
Caching فقط یک ابزار Performance نیست؛ یک تصمیم معماری است.
یک معماری Cache حرفهای
برای یک وبسایت مدرن میتوان معماریای شبیه این داشت:
User
│
▼
Browser Cache
│
Cache Miss
│
▼
CDN Edge
│
Cache Miss
│
▼
Web Server
│
▼
Application Cache
│
Cache Miss
│
▼
Redis
│
Cache Miss
│
▼
Database
در چنین معماری، هدف این است که درخواست تا حد امکان در نزدیکترین لایه ممکن پاسخ داده شود.
جمعبندی
Caching یکی از مهمترین ابزارهای Performance در معماری وب مدرن است؛ اما Cache فقط در Browser اتفاق نمیافتد.
چهار لایه مهمی که باید بشناسیم عبارتاند از:
Browser Cache
ذخیره منابع روی دستگاه کاربر و جلوگیری از دانلود مجدد.
CDN Cache
ذخیره محتوا در Edge Serverها و ارائه آن از نقطهای نزدیکتر به کاربر.
Server Cache
کاهش پردازشهای تکراری و جلوگیری از درخواستهای غیرضروری به منابع داخلی.
Application Cache
ذخیره نتیجه عملیات یا دادههای پرهزینه در منطق Application.
در کنار اینها، مفاهیمی مانند:
Cache-Control
ETag
TTL
Cache Hit / Miss
Cache Invalidation
Cache Busting
برای طراحی یک سیستم Cache قابل اعتماد اهمیت زیادی دارند.
در نهایت، هدف Caching این نیست که «همه چیز را ذخیره کنیم».
هدف این است که:
دادهای که احتمالاً دوباره لازم میشود را در مناسبترین لایه، برای مدت مناسب و با کمترین هزینه ممکن نگه داریم.
وقتی این استراتژی درست طراحی شود، نتیجه فقط یک سایت سریعتر نیست؛ بلکه Server سبکتر، Database کمفشارتر، هزینه زیرساخت پایینتر و تجربه کاربری بهتری خواهیم داشت.
