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, μπορεί να χρησιμοποιηθεί scheduled-cleanup (περιοδική διαγραφή όλων των ληγμένων εγγραφών) ή lazy-cleanup (διαγραφή μόνο κατά την πρόσβαση στην εγγραφή). Το 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 σημαίνει ότι η απάντηση μπορεί να αποθηκευτεί προσωρινά για 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 bit) που μειώνεται κατά 1 από κάθε δρομολογητή. Όταν το TTL φτάσει το 0, το πακέτο απορρίπτεται και ένα μήνυμα ICMP Time Exceeded επιστρέφεται στον αποστολέα. Αυτό αποτρέπει την απεριόριστη δρομολόγηση σε βρόχους δικτύου.
Οι εγγραφές DNS έχουν TTL που καθορίζει πόσο χρόνο ο επιλυτής (π.χ. προσωρινή μνήμη DNS του ISP) μπορεί να αποθηκεύει την εγγραφή χωρίς να ρωτά τον εξουσιοδοτημένο διακομιστή. Τυπικές τιμές: 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 ώρες, του διακριτικού ανανέωσης 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 ελέγχει τη λήξη σε κάθε πρόσβαση (lazy-cleanup) — οι ληγμένες εγγραφές διαγράφονται μόνο κατά την προσπάθεια πρόσβασης σε αυτές. Η μέθοδος 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 χρησιμοποιείται στην Πληροφορική (προσωρινές μνήμες, δίκτυα, 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 δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης