TTL (Time To Live) — پارامتری است که حداکثر زمانی را تعیین میکند که دادهها معتبر تلقی میشوند. پس از انقضای TTL، رکورد به عنوان منسوخ (stale) علامتگذاری شده و باید حذف یا بهروزرسانی شود. بر اساس Mozilla Developer Network (2026)، مکانیزم TTL پایه ذخیرهسازی HTTP از طریق هدر Cache-Control: max-age است و در تمام مرورگرهای مدرن و برنامههای موبایل برای بهینهسازی درخواستهای شبکه استفاده میشود.
نکات اصلی
TTL (Time To Live) — یک برچسب زمانی یا بازهای است که پس از آن دادهها نامعتبر تلقی میشوند. در زمینه کش کردن، TTL تعیین میکند که یک رکورد چه مدت میتواند در کش ذخیره شود قبل از اینکه نیاز به درخواست مجدد از منبع اصلی داشته باشد. در پروتکلهای شبکه، TTL عمر یک بسته را محدود کرده و از مسیریابی بینهایت جلوگیری میکند.
مقدار TTL همیشه بر حسب واحدهای زمان بیان میشود: میلیثانیه، ثانیه، دقیقه یا ساعت. پس از انقضای زمان تعیینشده، رکورد یا از کش حذف میشود یا به عنوان stale (منسوخ) علامتگذاری میشود. در درخواست بعدی به یک رکورد منسوخ، سیستم میتواند دادههای منسوخ را با بهروزرسانی بعدی بازگرداند (stale-while-revalidate) یا درخواست را تا دریافت دادههای تازه مسدود کند.
انتخاب TTL همیشه یک سازش بین بهروز بودن دادهها و عملکرد است. TTL بسیار کوتاه (1–5 ثانیه) برنامه را مجبور به انجام مکرر درخواستهای شبکه میکند و مزیت کش کردن را از بین میبرد. TTL بسیار طولانی (ساعتها/روزها) خطر نمایش اطلاعات منسوخ به کاربر را افزایش میدهد. مقدار بهینه به نوع داده بستگی دارد: نرخ ارز — ثانیهها، آب و هوا — دقیقهها، نسخه API — ساعتها.
TTL یک باطلسازی غیرفعال است: دادهها پس از انقضای زمان به طور خودکار حذف میشوند. جایگزین آن باطلسازی فعال است، جایی که منبع داده کش را از تغییرات مطلع میکند (مثلاً از طریق پیامهای WebSocket یا اعلانهای push). باطلسازی غیرفعال از طریق TTL در پیادهسازی سادهتر است اما بهروزرسانی فوری را تضمین نمیکند. باطلسازی فعال پیچیدهتر است اما به دادهها اجازه میدهد بدون تأخیرهای مشخصه TTL در حالت بهروز باقی بمانند.
مکانیزم TTL به دو روش قابل پیادهسازی است: انقضای مطلق (absolute expiration) و انقضای نسبی (relative expiration). در انقضای مطلق، رکورد زمان دقیقی را ذخیره میکند که در آن نامعتبر میشود. در انقضای نسبی — زمان ایجاد رکورد و TTL به عنوان بازه ثبت میشود و بررسی با محاسبه creationTime + TTL > currentTime انجام میشود.
در هر درخواست به کش، سیستم TTL هر رکورد را بررسی میکند. اگر TTL منقضی شده باشد، دادهها حذف یا به عنوان stale علامتگذاری میشوند و درخواست به منبع هدایت میشود. برای بهینهسازی بررسی TTL میتوان از پاکسازی زمانبندیشده (حذف دورهای تمام رکوردهای منقضی) یا پاکسازی تنبل (حذف فقط هنگام دسترسی به رکورد) استفاده کرد. پاکسازی تنبل از نظر حافظه کارآمدتر است زیرا به یک رشته پسزمینه برای اسکن کل کش نیاز ندارد.
در سیستمهای توزیعشده، TTL همچنین برای حل خودکار تعارضات استفاده میشود. به عنوان مثال، اگر دو سرور به طور همزمان مقادیر متفاوتی را برای یک کلید نوشته باشند، رکورد با TTL دیرتر میتواند اولویتدار تلقی شود. Amazon DynamoDB از TTL برای حذف خودکار رکوردهای منسوخ در جداول استفاده میکند — این یک ویژگی داخلی است که نیاز به مدیریت دستی ندارد.
برای افزایش عملکرد پس از انقضای TTL، از استراتژیهای خواندن دادههای منسوخ استفاده میشود. Stale-while-revalidate — بلافاصله دادههای منسوخ را به مشتری برگردان و همزمان بهروزرسانی پسزمینه را اجرا کن. Stale-if-error — اگر منبع موقتاً در دسترس نیست، دادههای منسوخ را برگردان. Cache-Aside (Lazy Loading) — در صورت عدم وجود در کش، دادهها را از منبع بارگیری کن، با TTL جدید در کش ذخیره کن و سپس به مشتری برگردان. هر استراتژی بر اساس الزامات سازگاری داده انتخاب میشود.
در برنامههای موبایل، TTL مکانیزم کلیدی مدیریت کش است. بیایید سناریوهای اصلی را بررسی کنیم که در آنها TTL رفتار برنامه و تجربه کاربر را تعیین میکند.
پروتکل HTTP یک مکانیزم داخلی TTL را از طریق هدرهای Cache-Control فراهم میکند. دستور max-age TTL را بر حسب ثانیه تعیین میکند: Cache-Control: public, max-age=3600 به این معنی است که پاسخ میتواند به مدت 1 ساعت کش شود. دستورالعملهای اضافی s-maxage (برای کشهای اشتراکی، مانند CDN) و stale-while-revalidate کنترل دقیقتری را فراهم میکنند. در صورت تطابق TTL با هدر expires، max-age به عنوان استاندارد مدرنتر HTTP/1.1 اولویت دارد.
| نوع داده | TTL توصیهشده | دلیل |
|---|---|---|
| آب و هوا | 10–30 دقیقه | پیشبینیها بیشتر بهروز نمیشوند |
| نرخ ارز | 15–60 ثانیه | نوسان بالا |
| فید خبری | 2–5 دقیقه | تعادل تازگی و عملکرد |
| پروفایل کاربر | 5–30 دقیقه | به ندرت در جلسه تغییر میکند |
| لیست محصولات | 10–60 دقیقه | قیمتها هر ثانیه تغییر نمیکنند |
| منابع استاتیک | 1–24 ساعت | نسخهگذاری از طریق URL یا ETag |
برای تصاویر، TTL میتواند به چند روز برسد، زیرا محتوا به ندرت تغییر میکند. با این حال، برنامههای موبایل اغلب از رویکرد ترکیبی استفاده میکنند: TTL کوتاه برای تصاویر بندانگشتی (30 دقیقه — بهروز بودن فریمها) و TTL طولانی برای تصاویر با اندازه کامل (7 روز). تصاویر با هدر HTTP Cache-Control: immutable اساساً نباید تا انقضای TTL دوباره درخواست شوند — این یک بهینهسازی برای منابع استاتیک است که در RFC 8246 پیشنهاد شده است. چنین تصاویری در سطح سیستم عامل (URLCache, OkHttp Cache) بدون دخالت برنامه کش میشوند.
در شبکهها، TTL نه برای کش کردن، بلکه برای محدود کردن عمر بستهها استفاده میشود. هر بسته IP دارای یک فیلد TTL (8 بیت) است که توسط هر مسیریاب 1 واحد کاهش مییابد. هنگامی که TTL به 0 میرسد، بسته دور انداخته میشود و پیام ICMP Time Exceeded به فرستنده بازگردانده میشود. این کار از مسیریابی بینهایت در حلقههای شبکه جلوگیری میکند.
رکوردهای DNS دارای TTL هستند که تعیین میکند resolver (مانند کش DNS ارائهدهنده اینترنت) چه مدت میتواند رکورد را بدون مراجعه به سرور معتبر ذخیره کند. مقادیر معمول: 300 ثانیه (5 دقیقه) برای رکوردهایی با تغییرات مکرر، 86400 ثانیه (24 ساعت) برای دامنههای پایدار. سرویسهای CDN اغلب TTL پایین (60–300 ثانیه) را برای هدایت سریع ترافیک در هنگام خرابی تنظیم میکنند، در حالی که دامنههای استاتیک ممکن است TTL تا 7 روز داشته باشند. هنگام مهاجرت سرور، توصیه میشود ابتدا TTL را به 60 ثانیه کاهش دهید (48 ساعت قبل از مهاجرت) تا تغییرات سریعاً منتشر شوند.
در برنامههای موبایل، TTL برای مدیریت جلسات و توکنهای دسترسی استفاده میشود. توکنهای JWT (JSON Web Tokens) حاوی فیلد exp (زمان انقضا) هستند که زمان مطلق Unix انقضا است. پس از انقضا، از توکن بازخوانی (refresh token) برای دریافت توکن دسترسی جدید بدون احراز هویت مجدد استفاده میشود. TTL توکن دسترسی معمولاً 1–24 ساعت و TTL توکن بازخوانی 7–30 روز است. این تعادل بین امنیت (TTL کوتاه خطر نشت را کاهش میدهد) و تجربه کاربری (TTL طولانی دفعات ورود مجدد را کاهش میدهد) است.
انتخاب TTL یک تصمیم مهندسی است که به نوع داده، SLA بهروزرسانی و هزینه درخواست مجدد بستگی دارد. استراتژیهای اصلی را بررسی میکنیم.
سادهترین رویکرد — همه رکوردها TTL یکسانی دارند. به عنوان مثال، کش کردن تمام پاسخهای API به مدت 5 دقیقه. مزیت: سادگی پیادهسازی و رفتار قابل پیشبینی. عیب: فرکانسهای مختلف تغییر انواع داده را در نظر نمیگیرد. TTL ثابت برای دادههای همگن که همه رکوردها «تازگی» یکسانی دارند، قابل توجیه است — به عنوان مثال، نرخ ارزهای دیجیتال در یک صرافی.
TTL بسته به رفتار دادهها به صورت پویا تغییر میکند. به عنوان مثال، اگر یک رکورد به ندرت روی سرور بهروز میشود، TTL افزایش مییابد؛ اگر مکرراً بهروز میشود — کاهش مییابد. پیادهسازی میتواند از هدرهای پاسخ HTTP استفاده کند: هدر Age (چند ثانیه پاسخ در کش بوده است) و هدر Date امکان محاسبه زمان باقیمانده زندگی را فراهم میکنند. TTL تطبیقی نسبت hit-ratio بهتری میدهد اما به منطق اضافی در سمت مشتری نیاز دارد.
Probabilistic Early Expiration (PEE) — تکنیکی که در آن TTL به صورت تصادفی در یک محدوده مشخص انتخاب میشود. این کار از «اثر گلّه» (thundering herd) جلوگیری میکند، زمانی که تعداد زیادی درخواست به طور همزمان منقضی میشوند و همه مشتریان به طور همزمان به منبع مراجعه میکنند. PEE به ویژه برای CDN و کشهای با بار بالا مفید است: به جای یک TTL واحد 300 ثانیهای، از یک مقدار تصادفی بین 240 تا 360 ثانیه استفاده میشود که بار روی منبع را به طور یکنواخت توزیع میکند.
بیایید پیادهسازی کش با TTL را در Kotlin با استفاده از انقضای مطلق بررسی کنیم. هر رکورد زمان ایجاد را ذخیره میکند و هنگام خواندن بررسی میشود که آیا TTL منقضی شده است یا خیر.
class TtlCache<K, V>(
private val defaultTtlMs: Long = 300000L
) {
private data class Entry<V>(
val value: V,
val createdAt: Long = System.currentTimeMillis()
)
private val map = ConcurrentHashMap<K, Entry<V>>()
fun get(key: K): V? {
val entry = map[key] ?: return null
if (isExpired(entry)) {
map.remove(key)
return null
}
return entry.value
}
fun put(key: K, value: V, ttlMs: Long = defaultTtlMs) {
map[key] = Entry(value, createdAt = System.currentTimeMillis() + ttlMs)
}
private fun isExpired(entry: Entry<*>): Boolean {
return System.currentTimeMillis() > entry.createdAt
}
fun cleanup() {
map.entries.removeIf { isExpired(it.value) }
}
}
کلاس Entry مقدار و زمان ایجاد + TTL (انقضای مطلق) را ذخیره میکند. متد get در هر بار دسترسی انقضا را بررسی میکند (پاکسازی تنبل) — رکوردهای منقضی فقط در هنگام تلاش برای دسترسی به آنها حذف میشوند. متد cleanup را میتوان به صورت دورهای از یک رشته پسزمینه برای حذف دستهای همه رکوردهای منسوخ فراخوانی کرد. ConcurrentHashMap ایمنی رشته را بدون مسدود کردن کل کش تضمین میکند.
در iOS برای کش کردن با TTL، استفاده از URLCache با پیکربندی memoryCapacity و diskCapacity راحت است. با این حال، URLCache از TTL فردی برای درخواستهای مختلف پشتیبانی نمیکند. بیایید یک پوشش سفارشی NSCache با پشتیبانی TTL را بررسی کنیم.
final class ApiResponseCache {
private var cache = NSCache<NSString, CacheEntry>()
func getResponse(for url: URL) -> Data? {
guard let entry = cache.object(forKey: url.absoluteString as NSString)
else { return nil }
guard entry.expirationDate > Date() else {
cache.removeObject(forKey: url.absoluteString as NSString)
return nil
}
return entry.data
}
func storeResponse(data: Data, for url: URL, ttl: TimeInterval) {
let entry = CacheEntry(data: data, expirationDate: Date().addingTimeInterval(ttl))
cache.setObject(entry, forKey: url.absoluteString as NSString)
}
}
final class CacheEntry: NSObject {
let data: Data
let expirationDate: Date
}
در این پیادهسازی، NSCache به عنوان یک ذخیرهگاه امن برای رشتهها استفاده میشود. CacheEntry حاوی Data و expirationDate است. هنگام get بررسی میشود که آیا زمان منقضی شده است یا خیر؛ اگر منقضی شده باشد — رکورد حذف شده و nil برگردانده میشود. TTL از طریق TimeInterval بر حسب ثانیه تنظیم میشود و میتواند برای هر URL متفاوت باشد: مقادیر معمول برای پاسخهای API 120 ثانیه برای محتوای پویا و 3600 برای دادههای استاتیک است.
سؤالات متداول
از نظر فنی TTL و تاریخ انقضا یکسان هستند: یک بازه زمانی که پس از آن دادهها نامعتبر تلقی میشوند. تفاوت در زمینه است: اصطلاح TTL در IT (کشها، شبکهها، DNS) استفاده میشود، در حالی که «تاریخ انقضا» بیشتر در منطق تجاری (کدهای تخفیف، اشتراکها) به کار میرود. در پیادهسازی، هر دو مکانیزم یکسان هستند — مقایسه زمان فعلی با زمان انقضا.
TTL بهینه به صورت تجربی انتخاب میشود. روش: با یک مقدار محافظهکارانه شروع کنید (30–60 ثانیه)، به تدریج افزایش دهید تا شکایتهایی درباره دادههای منسوخ ظاهر شود. نسبت hit-ratio کش را نظارت کنید: اگر زیر 70٪ است، TTL بیش از حد کوتاه است. SLA را در نظر بگیرید: برای دادههای مالی TTL میتواند 1 ثانیه، برای اخبار — 5 دقیقه، برای پروفایلها — 30 دقیقه باشد.
پس از انقضای max-age، مرورگر یا برنامه موبایل پاسخ را stale (منسوخ) در نظر میگیرد. در درخواست بعدی به همان URL، مشتری درخواستی با هدر If-None-Match (ETag) یا If-Modified-Since ارسال میکند. اگر دادهها تغییر نکرده باشند، سرور 304 Not Modified بدون بدنه پاسخ برمیگرداند و TTL تمدید میشود. اگر تغییر کرده باشند — سرور 200 را با دادههای جدید و Cache-Control جدید برمیگرداند.
از نظر فنی TTL میتواند بسیار طولانی باشد (max-age=31536000 — 1 سال)، اما این به ندرت قابل توجیه است. حتی منابع استاتیک ممکن است تغییر کنند و مشتری تا انقضای TTL از آن مطلع نخواهد شد. توصیه میشود از URLهای نسخهبندی شده (style.css?v=2) با TTL طولانی استفاده کنید: وقتی فایل تغییر میکند، URL تغییر میکند و کش قدیمی به طور خودکار منسوخ میشود.
TTL و استراتژیهای حذف (LRU, FIFO) وظایف متفاوتی را حل میکنند. TTL تعیین میکند که چه زمانی دادهها منسوخ میشوند — این یک معیار زمانی است. LRU و FIFO تعیین میکنند که کدام دادهها در هنگام پر شدن کش حذف شوند — این یک معیار مکانی است. آنها میتوانند ترکیب شوند: یک رکورد حذف میشود اگر TTL منقضی شده باشد یا کش پر شده باشد (بر اساس LRU/FIFO). در سیستمهای تولیدی، هر دو مکانیسم با هم کار میکنند.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید