Caching یا کشینگ به معنی ذخیرهسازی موقت خروجی محاسبات یا دادههای پرمصرف برای کاهش زمان پاسخ و فشار روی منبع اصلی است. کش میتواند در مرورگر، CDN، برنامه، حافظه سرور یا دیتابیس وجود داشته باشد.
چه چیزی را کش کنیم؟
در یک فروشگاه، فهرست دستهبندیها و محصول پرفروش برای کش مناسباند، ولی قیمت نهایی پرداخت و موجودی حساس باید سیاست تازگی داده روشنی داشته باشند. کش، منبع نهایی حقیقت نیست مگر اینکه معماری صریحاً خلاف آن را طراحی کرده باشد.
ابزارها و لایهها
| ابزار یا لایه | کاربرد | نکته |
|---|---|---|
| ردیس | کش توزیعشده، صف، داده ساختمند | پشتیبانی TTL و انواع داده |
| ممکشدی | کش ساده توزیعشده در حافظه | ساختار ساده و سرعت بالا |
| APCu | کش محلی پروسسهای PHP | اشتراک بین سرورها ندارد |
| Caffeine | کش پرکاربرد در JVM | مناسب کش درون برنامه جاوا |
| IMemoryCache | کش درون پردازش در ASP.NET Core | در چند سرور نیازمند راهبرد تکمیلی |
| شبکه توزیع محتوا | کش دارایی و بعضی پاسخهای HTTP | مدیریت هدر و Purge |
| Varnish / Nginx | Reverse Proxy Cache | مناسب پاسخهای قابل کش |
نمونه لاراول با Cache::remember
use Illuminate\Support\Facades\Cache;
$products = Cache::remember('catalog:featured', 300, function () {
return Product::query()->where('featured', true)->get();
});
Cache::forget('catalog:featured');
Python با Redis
import redis
client = redis.Redis(host='localhost', port=6379, decode_responses=True)
key = 'catalog:featured'
value = client.get(key)
if value is None:
value = '{"products":[1,2,3]}' # computed from the source
client.set(key, value, ex=300)
Go با Redis
ctx := context.Background()
rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379"})
if err := rdb.Set(ctx, "catalog:featured", "cached result", 5*time.Minute).Err(); err != nil {
log.Fatal(err)
}
value, err := rdb.Get(ctx, "catalog:featured").Result()
ASP.NET Core با IMemoryCache
builder.Services.AddMemoryCache();
// In a service receiving IMemoryCache cache via DI:
var products = cache.GetOrCreate("featured-products", entry => {
entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5);
return LoadFeaturedProducts();
});
روشهای بهروزرسانی کش
- Cache-aside: برنامه ابتدا کش را میخواند و در Miss سراغ دیتابیس میرود.
- Write-through: هنگام نوشتن، منبع و کش هماهنگ میشوند.
- Write-behind: نوشتن در منبع اصلی با تاخیر انجام میشود و به تضمین ماندگاری نیاز دارد.
- TTL و Invalidation: برای جلوگیری از باقیماندن داده قدیمی باید سیاست روشن باشد.
نکته فنی
وقتی کلید پرطرفدار همزمان برای هزار درخواست منقضی شود، کش استمپید رخ میدهد. قفل بازسازی، Jitter در TTL و Stale-While-Revalidate از راهکارها هستند. برای آشنایی با راهکارهای مقابله و مثال قفلگذاری، صفحه کش استمپید را مطالعه کنید.
اصطلاحات مرتبط: کش اینولیدیشن، کش استمپید، ردیس، ممکشدی، هدرهای HTTP، کنترل کش HTTP، شبکه توزیع محتوا.
برای بررسی راهکارهای قفل کش، زمان انقضای تصادفی و بازسازی پیشدستانه، مقاله روشهای جلوگیری از Cache Stampede همراه با مثال در باورژن را مطالعه کنید.