TTL (Time To Live) là một tham số xác định thời gian tối đa mà dữ liệu được coi là hợp lệ. Sau khi TTL hết hạn, bản ghi được đánh dấu là cũ (stale) và phải được xóa hoặc cập nhật. Theo Mozilla Developer Network (2026), cơ chế TTL là nền tảng của bộ nhớ đệm HTTP thông qua tiêu đề Cache-Control: max-age và được sử dụng trong tất cả các trình duyệt hiện đại và ứng dụng di động để tối ưu hóa các yêu cầu mạng.
Điểm chính
TTL (Time To Live) là một dấu thời gian hoặc khoảng thời gian mà sau đó dữ liệu được coi là không hợp lệ. Trong bối cảnh bộ nhớ đệm, TTL xác định một bản ghi có thể được lưu trong bộ nhớ đệm bao lâu trước khi cần được lấy lại từ nguồn. Trong giao thức mạng, TTL giới hạn vòng đời của gói tin, ngăn chặn định tuyến vô hạn.
Giá trị TTL luôn được biểu thị bằng đơn vị thời gian: mili giây, giây, phút hoặc giờ. Sau khi thời gian đã đặt trôi qua, bản ghi sẽ bị xóa khỏi bộ nhớ đệm hoặc được đánh dấu là cũ. Khi yêu cầu tiếp theo đến một bản ghi cũ, hệ thống có thể trả về dữ liệu cũ kèm cập nhật sau đó (stale-while-revalidate) hoặc chặn yêu cầu cho đến khi có dữ liệu mới.
Chọn TTL luôn là sự đánh đổi giữa tính mới của dữ liệu và hiệu suất. TTL quá ngắn (1–5 giây) buộc ứng dụng thực hiện các yêu cầu mạng thường xuyên, làm mất lợi ích của bộ nhớ đệm. TTL quá dài (giờ/ngày) làm tăng nguy cơ hiển thị thông tin lỗi thời cho người dùng. Giá trị tối ưu phụ thuộc vào loại dữ liệu: tỷ giá — giây, thời tiết — phút, phiên bản API — giờ.
TTL là vô hiệu hóa thụ động: dữ liệu được tự động xóa sau một khoảng thời gian. Giải pháp thay thế là vô hiệu hóa chủ động, nơi nguồn dữ liệu thông báo cho bộ nhớ đệm về các thay đổi (ví dụ: qua tin nhắn WebSocket hoặc thông báo push). Vô hiệu hóa thụ động qua TTL đơn giản hơn để triển khai nhưng không đảm bảo tính mới tức thời. Vô hiệu hóa chủ động phức tạp hơn nhưng cho phép giữ dữ liệu cập nhật mà không có độ trễ vốn có của TTL.
Cơ chế TTL có thể được triển khai theo hai cách: hết hạn tuyệt đối (absolute expiration) và hết hạn tương đối (relative expiration). Với hết hạn tuyệt đối, bản ghi lưu trữ thời gian cụ thể khi nó trở nên không hợp lệ. Với hết hạn tương đối, thời gian tạo của bản ghi và TTL dưới dạng khoảng thời gian được ghi lại và việc kiểm tra được thực hiện bằng cách tính creationTime + TTL > currentTime.
Ở mỗi yêu cầu đến bộ nhớ đệm, hệ thống kiểm tra TTL của mỗi bản ghi. Nếu TTL đã hết hạn, dữ liệu sẽ bị xóa hoặc đánh dấu là cũ và yêu cầu được chuyển tiếp đến nguồn. Để tối ưu hóa việc kiểm tra TTL, có thể sử dụng dọn dẹp theo lịch trình (xóa định kỳ tất cả các bản ghi đã hết hạn) hoặc dọn dẹp lười (chỉ xóa khi truy cập vào bản ghi). Dọn dẹp lười hiệu quả hơn về bộ nhớ vì không yêu cầu luồng nền để quét toàn bộ bộ nhớ đệm.
Trong hệ thống phân tán, TTL cũng được sử dụng để giải quyết xung đột tự động. Ví dụ, nếu hai máy chủ đồng thời ghi các giá trị khác nhau cho cùng một khóa, bản ghi có TTL muộn hơn có thể được coi là ưu tiên hơn. Amazon DynamoDB sử dụng TTL để tự động xóa các bản ghi lỗi thời trong các bảng — đây là tính năng tích hợp sẵn không yêu cầu quản lý thủ công.
Để cải thiện hiệu suất khi TTL hết hạn, các chiến lược đọc dữ liệu cũ được sử dụng. Stale-while-revalidate — ngay lập tức trả về dữ liệu cũ cho khách hàng và đồng thời khởi chạy cập nhật nền. Stale-if-error — trả về dữ liệu cũ nếu nguồn tạm thời không khả dụng. Cache-Aside (Lazy Loading) — khi không có trong bộ nhớ đệm, tải dữ liệu từ nguồn, lưu vào bộ nhớ đệm với TTL mới và sau đó mới trả về cho khách hàng. Mỗi chiến lược được chọn dựa trên yêu cầu nhất quán dữ liệu.
Trong các ứng dụng di động, TTL là cơ chế chính để quản lý bộ nhớ đệm. Hãy xem các kịch bản chính nơi TTL xác định hành vi của ứng dụng và trải nghiệm người dùng.
Giao thức HTTP cung cấp cơ chế TTL tích hợp thông qua các tiêu đề Cache-Control. Chỉ thị max-age đặt TTL tính bằng giây: Cache-Control: public, max-age=3600 có nghĩa là phản hồi có thể được lưu vào bộ nhớ đệm trong 1 giờ. Các chỉ thị bổ sung s-maxage (cho bộ nhớ đệm dùng chung, ví dụ: CDN) và stale-while-revalidate cung cấp khả năng kiểm soát chi tiết hơn. Khi TTL trùng với tiêu đề expires, max-age được ưu tiên như tiêu chuẩn HTTP/1.1 hiện đại hơn.
| Loại dữ liệu | TTL đề xuất | Lý do |
|---|---|---|
| Thời tiết | 10–30 phút | Dự báo không được cập nhật thường xuyên |
| Tỷ giá | 15–60 giây | Biến động cao |
| Bản tin | 2–5 phút | Cân bằng giữa tính mới và hiệu suất |
| Hồ sơ người dùng | 5–30 phút | Hiếm khi thay đổi trong phiên |
| Danh sách sản phẩm | 10–60 phút | Giá không thay đổi mỗi giây |
| Tài nguyên tĩnh | 1–24 giờ | Được quản lý phiên bản qua URL hoặc ETag |
Đối với hình ảnh, TTL có thể đạt đến vài ngày vì nội dung hiếm khi thay đổi. Tuy nhiên, các ứng dụng di động thường sử dụng phương pháp kết hợp: TTL ngắn cho hình xem trước (30 phút — tính mới của khung hình) và TTL dài cho hình ảnh kích thước đầy đủ (7 ngày). Hình ảnh có tiêu đề HTTP Cache-Control: immutable không nên được yêu cầu lại cho đến khi TTL hết hạn — đây là tối ưu hóa cho tài nguyên tĩnh được đề xuất trong RFC 8246. Các hình ảnh này được lưu vào bộ nhớ đệm ở cấp hệ điều hành (URLCache, OkHttp Cache) mà không có sự tham gia của ứng dụng.
Trong mạng, TTL không được sử dụng cho bộ nhớ đệm mà để giới hạn vòng đời của gói tin. Mỗi gói IP chứa một trường TTL (8 bit), được giảm đi 1 bởi mỗi bộ định tuyến. Khi TTL đạt 0, gói tin bị loại bỏ và người gửi nhận được thông báo ICMP Time Exceeded. Điều này ngăn chặn định tuyến vô hạn trong các vòng lặp mạng.
Các bản ghi DNS có TTL xác định trình phân giải (ví dụ: bộ nhớ đệm DNS của ISP) có thể lưu trữ bản ghi mà không cần truy vấn máy chủ có thẩm quyền trong bao lâu. Giá trị điển hình: 300 giây (5 phút) cho các bản ghi có thay đổi thường xuyên, 86400 giây (24 giờ) cho các miền ổn định. Các dịch vụ CDN thường đặt TTL thấp (60–300 giây) để định tuyến lại lưu lượng nhanh khi có sự cố, trong khi các miền tĩnh có thể có TTL lên đến 7 ngày. Khi di chuyển máy chủ, nên giảm TTL xuống 60 giây trước (48 giờ trước khi di chuyển) để các thay đổi lan truyền nhanh chóng.
Trong các ứng dụng di động, TTL được sử dụng để quản lý phiên và token truy cập. Token JWT (JSON Web Tokens) chứa trường exp (thời gian hết hạn), là thời gian hết hạn Unix tuyệt đối. Sau khi hết hạn, token làm mới được sử dụng để lấy token truy cập mới mà không cần xác thực lại. TTL của token truy cập thường là 1–24 giờ, TTL của token làm mới là 7–30 ngày. Đây là sự cân bằng giữa bảo mật (TTL ngắn giảm rủi ro rò rỉ) và UX (TTL dài giảm tần suất đăng nhập lại).
Chọn TTL là một quyết định kỹ thuật phụ thuộc vào loại dữ liệu, SLA về tính mới và chi phí của yêu cầu lại. Hãy xem xét các chiến lược chính.
Cách tiếp cận đơn giản nhất — tất cả các bản ghi đều có cùng TTL. Ví dụ: lưu trữ tất cả phản hồi API vào bộ nhớ đệm trong 5 phút. Ưu điểm: đơn giản khi triển khai và hành vi có thể dự đoán trước. Nhược điểm: không tính đến tần suất thay đổi khác nhau của các loại dữ liệu khác nhau. TTL cố định phù hợp cho dữ liệu đồng nhất, nơi tất cả các bản ghi có cùng “tính mới” — ví dụ: tỷ giá tiền mã hóa trên cùng một sàn giao dịch.
TTL thay đổi linh hoạt dựa trên hành vi của dữ liệu. Ví dụ, nếu một bản ghi hiếm khi được cập nhật trên máy chủ, TTL sẽ tăng; nếu nó được cập nhật thường xuyên — sẽ giảm. Việc triển khai có thể sử dụng các tiêu đề phản hồi HTTP: tiêu đề Age (phản hồi đã ở trong bộ nhớ đệm bao nhiêu giây) và tiêu đề Date cho phép tính toán thời gian sống còn lại. TTL thích ứng cung cấp tỷ lệ truy cập tốt hơn nhưng yêu cầu thêm logic phía máy khách.
Probabilistic Early Expiration (PEE) — một kỹ thuật trong đó TTL được chọn ngẫu nhiên trong một phạm vi nhất định. Điều này ngăn chặn hiệu ứng “đàn gia súc” (thundering herd), nơi nhiều yêu cầu hết hạn đồng thời và tất cả khách hàng cùng truy cập vào nguồn. PEE đặc biệt hữu ích cho CDN và bộ nhớ đệm có tải cao: thay vì một TTL duy nhất là 300 giây, một giá trị ngẫu nhiên từ 240 đến 360 giây được sử dụng, phân bổ tải đều lên nguồn.
Hãy xem triển khai bộ nhớ đệm với TTL trong Kotlin sử dụng hết hạn tuyệt đối. Mỗi bản ghi lưu trữ thời gian tạo của nó và khi đọc sẽ kiểm tra xem TTL đã hết hạn chưa.
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) }
}
}
Lớp Entry lưu trữ giá trị và thời gian tạo + TTL (hết hạn tuyệt đối). Phương thức get kiểm tra hết hạn ở mỗi lần truy cập (dọn dẹp lười) — các bản ghi đã hết hạn chỉ bị xóa khi cố gắng truy cập chúng. Phương thức cleanup có thể được gọi định kỳ từ một luồng nền để xóa hàng loạt tất cả các bản ghi lỗi thời. ConcurrentHashMap cung cấp an toàn luồng mà không khóa toàn bộ bộ nhớ đệm.
Trên iOS, bạn có thể sử dụng URLCache với các cài đặt memoryCapacity và diskCapacity để lưu trữ vào bộ nhớ đệm với TTL. Tuy nhiên, URLCache không hỗ trợ TTL riêng cho các yêu cầu khác nhau. Hãy xem xét một wrapper tùy chỉnh NSCache hỗ trợ 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
}
Trong triển khai này, NSCache được sử dụng như một kho lưu trữ an toàn luồng. CacheEntry chứa Data và expirationDate. Khi get được gọi, nó kiểm tra xem thời gian đã hết hạn chưa; nếu rồi, bản ghi sẽ bị xóa và nil được trả về. TTL được đặt bằng giây thông qua TimeInterval và có thể khác nhau cho mỗi URL: các giá trị điển hình cho phản hồi API là 120 giây cho nội dung động và 3600 cho dữ liệu tĩnh.
Câu hỏi thường gặp
Về mặt kỹ thuật, TTL và ngày hết hạn là giống nhau: một khoảng thời gian mà sau đó dữ liệu được coi là không hợp lệ. Sự khác biệt là ở ngữ cảnh: thuật ngữ TTL được sử dụng trong CNTT (bộ nhớ đệm, mạng, DNS), trong khi “ngày hết hạn” thường được áp dụng trong logic kinh doanh (mã khuyến mại, đăng ký). Trong triển khai, cả hai cơ chế đều giống nhau — so sánh thời gian hiện tại với thời gian hết hạn.
TTL tối ưu được chọn theo kinh nghiệm. Phương pháp: bắt đầu với giá trị thận trọng (30–60 giây), tăng dần cho đến khi xuất hiện phàn nàn về dữ liệu lỗi thời. Theo dõi tỷ lệ truy cập bộ nhớ đệm: nếu dưới 70%, TTL quá ngắn. Cân nhắc SLA: đối với dữ liệu tài chính, TTL có thể là 1 giây; cho tin tức — 5 phút; cho hồ sơ — 30 phút.
Sau khi max-age hết hạn, trình duyệt hoặc ứng dụng di động coi phản hồi là cũ (stale). Ở yêu cầu tiếp theo đến cùng URL, máy khách gửi yêu cầu với tiêu đề If-None-Match (ETag) hoặc If-Modified-Since. Nếu dữ liệu không thay đổi, máy chủ trả về 304 Not Modified mà không có nội dung phản hồi và TTL được cập nhật. Nếu đã thay đổi, máy chủ trả về 200 với dữ liệu mới và Cache-Control mới.
Về mặt kỹ thuật, TTL có thể rất lớn (max-age=31536000 — 1 năm), nhưng điều này hiếm khi chính đáng. Ngay cả tài nguyên tĩnh cũng có thể thay đổi và máy khách sẽ không biết cho đến khi TTL hết hạn. Nên sử dụng URL có quản lý phiên bản (style.css?v=2) với TTL dài: khi tệp thay đổi, URL thay đổi và bộ nhớ đệm cũ tự động trở nên lỗi thời.
TTL và các chiến lược loại bỏ (LRU, FIFO) giải quyết các vấn đề khác nhau. TTL xác định khi nào dữ liệu trở nên không liên quan — đây là tiêu chí thời gian. LRU và FIFO xác định dữ liệu nào cần xóa khi bộ nhớ đệm đầy — đây là tiêu chí không gian. Chúng có thể được kết hợp: một bản ghi bị xóa nếu TTL đã hết hạn HOẶC bộ nhớ đệm đầy (theo LRU/FIFO). Trong các hệ thống sản xuất, cả hai cơ chế hoạt động cùng nhau.
Tổng kết
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm