TTL (Time To Live) — هو معلم يحدد أقصى مدة زمنية تظل خلالها البيانات صالحة. بعد انتهاء TTL، يتم وسم السجل بأنه قديم (stale) ويجب حذفه أو تحديثه. وفقًا لـ Mozilla Developer Network (2026)، فإن آلية TTL هي أساس التخزين المؤقت HTTP من خلال رأس Cache-Control: max-age وتستخدم في جميع المتصفحات الحديثة وتطبيقات الهواتف المحمولة لتحسين طلبات الشبكة.
النقاط الرئيسية
TTL (Time To Live) — هو طابع زمني أو فاصل، بعده تعتبر البيانات غير صالحة. في سياق التخزين المؤقت، يحدد TTL مدة الزمن التي يمكن للسجل أن يبقى في الذاكرة المؤقتة قبل أن يحتاج إلى إعادة الطلب من المصدر. في بروتوكولات الشبكة، يحد TTL من عمر حزمة البيانات، ممنعًا التوجيه لا نهاية له.
يتم دائمًا تعبير قيمة TTL بوحدات الوقت: ملي ثانية، ثوانٍ، دقائق أو ساعات. بعد انتهاء الوقت المحدد، يتم إما حذف السجل من الذاكرة المؤقتة أو وسمه بأنه قديم. عند الطلب التالي لسجل قديم، يمكن للنظام إما إعادة البيانات القديمة مع تحديث لاحق (stale-while-revalidate) أو حجب الطلب حتى الحصول على بيانات جديدة.
اختيار TTL هو دائمًا مقايضة بين حداثة البيانات والأداء. TTL قصير جدًا (1–5 ثوانٍ) يجبر التطبيق على إجراء طلبات شبكة متكررة، مما يلغي فائدة التخزين المؤقت. TTL طويل جدًا (ساعات/أيام) يزيد من خطر عرض معلومات قديمة للمستخدم. تعتمد القيمة المثلى على نوع البيانات: أسعار الصرف — ثوانٍ، الطقس — دقائق، إصدار API — ساعات.
TTL هو إبطال سلبي: يتم حذف البيانات تلقائيًا بعد فترة زمنية. البديل هو الإبطال النشط، حيث يقوم مصدر البيانات بإشعار الذاكرة المؤقتة بالتغييرات (على سبيل المثال، عبر رسائل WebSocket أو إشعارات دفع). الإبطال السلبي عبر TTL أبسط في التنفيذ ولكنه لا يضمن الحداثة الفورية. الإبطال النشط أكثر تعقيدًا ولكنه يسمح بالحفاظ على حداثة البيانات دون التأخيرات المتأصلة بـ TTL.
يمكن تنفيذ آلية TTL بطريقتين: الانتهاء المطلق (absolute expiration) والانتهاء النسبي (relative expiration). في الانتهاء المطلق، يخزن السجل الوقت المحدد عندما يصبح غير صالح. في الانتهاء النسبي، يتم تسجيل وقت إنشاء السجل و TTL كفاصل، ويتم التحقق بحساب creationTime + TTL > currentTime.
عند كل طلب للذاكرة المؤقتة، يتحقق النظام من TTL لكل سجل. إذا كان TTL قد انتهى، يتم حذف البيانات أو وسمها بأنها قديمة، ويتم توجيه الطلب إلى المصدر. لتحسين التحقق من TTL، يمكن استخدام التنظيف المجدول (حذف دوري لجميع السجلات المنتهية) أو التنظيف الكسول (lazy cleanup) — الحذف فقط عند الوصول إلى السجل. التنظيف الكسول أكثر كفاءة في استخدام الذاكرة لأنه لا يتطلب خيط خلفية لمسح الذاكرة المؤقتة بأكملها.
في الأنظمة الموزعة، يستخدم 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 تعني أن الاستجابة يمكن تخزينها مؤقتًا لمدة ساعة واحدة. توجيهات إضافية 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 يحدد مدة الزمن التي يمكن للمحلل (على سبيل المثال، ذاكرة DNS لمزود الخدمة) تخزين السجل دون استعلام الخادم الموثوق. القيم النموذجية: 300 ثانية (5 دقائق) للسجلات ذات التغييرات المتكررة، 86400 ثانية (24 ساعة) للنطاقات المستقرة. تحدد خدمات CDN غالبًا TTL منخفض (60–300 ثانية) لإعادة توجيه سريع للحركة أثناء الأعطال، بينما يمكن أن يكون للنطاقات الثابتة TTL يصل إلى 7 أيام. عند ترحيل خادم، يوصى بخفض TTL أولاً إلى 60 ثانية (48 ساعة قبل الترحيل) لتنتشر التغييرات بسرعة.
في تطبيقات الهواتف المحمولة، يستخدم TTL لإدارة الجلسات ورموز الوصول. تحتوي رموز JWT (رموز الويب JSON) على حقل exp (وقت الانتهاء)، وهو وقت Unix مطلق للانتهاء. بعد الانتهاء، يتم استخدام رمز التحديث للحصول على رمز وصول جديد دون إعادة المصادقة. عادةً ما يكون TTL لرمز الوصول 1–24 ساعة، و TTL لرمز التحديث 7–30 يومًا. هذا هو توازن بين الأمان (TTL قصير يقلل من خطر التسريب) وتجربة المستخدم (TTL طويل يقلل تكرار إعادات تسجيل الدخول).
اختيار TTL هو قرار هندسي يعتمد على نوع البيانات، و SLA الحداثة، وتكلفة إعادة الطلب. دعنا ننظر إلى الاستراتيجيات الرئيسية.
أبسط نهج — جميع السجلات لها نفس TTL. على سبيل المثال، تخزين جميع استجابات API مؤقتًا لمدة 5 دقائق. المزية: بساطة التنفيذ والسلوك المتوقع. العيب: لا يراعي اختلاف تردد تغيير أنواع البيانات المختلفة. TTL الثابت مبرر للبيانات المتجانسة حيث جميع السجلات لها نفس الحداثة — على سبيل المثال، أسعار العملات الرقمية في بورصة واحدة.
يتغير TTL ديناميكيًا بناءً على سلوك البيانات. على سبيل المثال، إذا كان السجل نادرًا ما يتم تحديثه على الخادم، يزداد TTL؛ إذا تم تحديثه بشكل متكرر — ينخفض. يمكن للتنفيذ استخدام رؤوس استجابة HTTP: يسمح رأس Age (عدد الثواني التي قضتها الاستجابة في الذاكرة المؤقتة) ورأس Date بحساب الوقت المتبقي من العمر. يوفر TTL التكيفي نسبة إصابة أفضل ولكنه يتطلب منطقًا إضافيًا على العميل.
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، من المناسب استخدام URLCache مع إعدادات memoryCapacity و diskCapacity للتخزين المؤقت مع TTL. ولكن 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 في تكنولوجيا المعلومات (التخزين المؤقت، الشبكات، DNS)، بينما يطبق «تاريخ انتهاء الصلاحية» أكثر في منطق الأعمال (أكواد الخصم، الاشتراكات). في التنفيذ، كلتا الآليتين متطابقتان — مقارنة الوقت الحالي بوقت الانتهاء.
يتم اختيار TTL الأمثل تجريبيًا. المنهجية: ابدأ بقيمة محافظة (30–60 ثانية)، زد تدريجيًا حتى ظهور شكاوى حول بيانات قديمة. راقب نسبة الإصابات للذاكرة المؤقتة: إذا كانت أقل من 70%، فإن TTL قصير جدًا. وضع في اعتبارك SLA: للبيانات المالية، يمكن أن يكون TTL ثانية واحدة؛ للأخبار — 5 دقائق؛ للملفات الشخصية — 30 دقيقة.
بعد انتهاء max-age، يعتبر المتصفح أو تطبيق الهاتف المحمول الاستجابة قديمة. عند الطلب التالي لنفس URL، يرسل العميل طلبًا مع رأس If-None-Match (ETag) أو If-Modified-Since. إذا لم تتغير البيانات، يعيد الخادم 304 Not Modified دون جسم استجابة، ويتم تحديث TTL. إذا تغيرت، يعيد الخادم 200 مع بيانات جديدة و Cache-Control جديد.
تقنياً، يمكن أن يكون TTL كبيرًا جدًا (max-age=31536000 — سنة واحدة)، ولكن هذا نادراً ما يكون مبررًا. حتى الموارد الثابتة يمكن أن تتغير، ولن يعلم العميل بذلك حتى ينتهي TTL. يوصى باستخدام URLs مزودة بإصدار (style.css?v=2) مع TTL طويل: عند تغيير الملف، يتغير URL، وتصبح الذاكرة المؤقتة القديمة غير صالحة تلقائيًا.
TTL واستراتيجيات الإزالة (LRU، FIFO) تحل مشاكل مختلفة. TTL يحدد متى تصبح البيانات غير ذات صلة — هذا معيار زمني. LRU و FIFO يحددان البيانات التي يجب إزالتها عند امتلاء الذاكرة المؤقتة — هذا معيار مكاني. يمكن الجمع بينهما: يتم حذف السجل إذا انتهى TTL أو امتلأت الذاكرة المؤقتة (بواسطة LRU/FIFO). في أنظمة الإنتاج، تعمل كلتا الآليتين معًا.
الملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.