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 สามารถใช้การทำความสะอาดตามกำหนดเวลา (การลบเรกคอร์ดที่หมดอายุทั้งหมดเป็นระยะ) หรือการทำความสะอาดแบบขี้เกียจ (ลบเฉพาะเมื่อเข้าถึงเรกคอร์ด) การทำความสะอาดแบบขี้เกียจ มีประสิทธิภาพด้านหน่วยความจำมากกว่าเนื่องจากไม่ต้องใช้เธรดพื้นหลังเพื่อสแกนทั้งแคช
ในระบบกระจาย 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 ที่กำหนดว่าเรโซลฟ์เวอร์ (ตัวอย่างเช่น แคช DNS ของ ISP) สามารถเก็บเรกคอร์ดโดยไม่ต้องสอบถามเซิร์ฟเวอร์ผู้มีอำนาจนานเท่าใด ค่าทั่วไป: 300 วินาที (5 นาที) สำหรับเรกคอร์ดที่มีการเปลี่ยนแปลงบ่อย, 86400 วินาที (24 ชั่วโมง) สำหรับโดเมนที่เสถียร บริการ CDN มักตั้งค่า TTL ต่ำ (60–300 วินาที) สำหรับการเปลี่ยนเส้นทางทราฟฟิกอย่างรวดเร็วระหว่างที่เกิดข้อผิดพลาด ในขณะที่โดเมนคงที่สามารถมี TTL สูงถึง 7 วัน เมื่อย้ายเซิร์ฟเวอร์ ขอแนะนำให้ลด TTL ลงเหลือ 60 วินาทีก่อน (48 ชั่วโมงก่อนการย้าย) เพื่อให้การเปลี่ยนแปลงแพร่กระจายอย่างรวดเร็ว
ในแอปพลิเคชันมือถือ TTL ใช้สำหรับจัดการเซสชันและโทเคนการเข้าถึง โทเคน JWT (JSON Web Tokens) มีฟิลด์ exp (เวลาหมดอายุ) ซึ่งเป็นเวลาหมดอายุ Unix แบบสัมบูรณ์ หลังจากหมดอายุ โทเคนรีเฟรชจะใช้เพื่อรับโทเคนการเข้าถึงใหม่โดยไม่ต้องยืนยันตัวตนอีกครั้ง TTL ของโทเคนการเข้าถึงโดยปกติคือ 1–24 ชั่วโมง TTL ของโทเคนรีเฟรชคือ 7–30 วัน นี่คือความสมดุลระหว่างความปลอดภัย (TTL สั้นลดความเสี่ยงของการรั่วไหล) และ UX (TTL ยาวลดความถี่ของการเข้าสู่ระบบซ้ำ)
การเลือก TTL เป็นการตัดสินใจทางวิศวกรรมที่ขึ้นอยู่กับประเภทข้อมูล SLA ความสดใหม่ และต้นทุนของการขอซ้ำ มาพิจารณากลยุทธ์หลักกัน
วิธีที่ง่ายที่สุด — เรกคอร์ดทั้งหมดมี TTL เดียวกัน ตัวอย่างเช่น แคชการตอบสนอง API ทั้งหมดเป็นเวลา 5 นาที ข้อดี: ความเรียบง่ายของการใช้งานและพฤติกรรมที่คาดการณ์ได้ ข้อเสีย: ไม่คำนึงถึงความถี่การเปลี่ยนแปลงที่แตกต่างกันของข้อมูลประเภทต่างๆ TTL คงที่ เหมาะสมสำหรับข้อมูลที่เป็นเนื้อเดียวกันที่เรกคอร์ดทั้งหมดมี “ความสดใหม่” เท่ากัน — ตัวอย่างเช่น อัตราคริปโตเคอร์เรนซีบน exchange เดียวกัน
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 wrapper ที่กำหนดเองพร้อมรองรับ 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 สามารถเป็น 1 วินาที; สำหรับข่าว — 5 นาที; สำหรับโปรไฟล์ — 30 นาที
หลังจาก max-age หมดอายุ เบราว์เซอร์หรือแอปพลิเคชันมือถือจะถือว่าการตอบสนองล้าสมัย ในการขอครั้งต่อไปยัง 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 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม