SCT

กำลังเตรียมประสบการณ์ดิจิทัล

ลดหน่วยความจำได้ 100 เทระไบต์ด้วยการจัดโครงสร้างข้อมูลใหม่: บทเรียนจากแคช DNS ระดับโลก

เมื่อระบบมีรายการแคชกว่า 250,000 ล้านรายการ การเปลืองหน่วยความจำเพียงหนึ่งไบต์ต่อรายการเท่ากับสูญเปล่าไปกว่า 250 กิกะไบต์ บทความนี้ถอดวิธีลดขนาดต่อรายการลง 56% ทีละขั้น พร้อมบทเรียนเรื่องการวัดผลที่ทีมไทยนำไปใช้กับระบบของตัวเองได้

เมื่อระบบมีรายการแคชกว่า 250,000 ล้านรายการ การเปลืองหน่วยความจำเพียงหนึ่งไบต์ต่อรายการเท่ากับสูญเปล่าไปกว่า 250 กิกะไบต์ บทความนี้ถอดวิธีลดขนาดต่อรายการลง 56% ทีละขั้น พร้อมบทเรียนเรื่องการวัดผลที่ทีมไทยนำไปใช้กับระบบของตัวเองได้

โจทย์: หนึ่งไบต์ที่คูณด้วย 250,000 ล้าน

แพลตฟอร์ม DNS ที่บทความพูดถึงดูแลรายการแคชรวมกันมากกว่า 250,000 ล้านรายการทั่วทั้งฟลีต ที่ขนาดนี้ตัวเลขเล็ก ๆ กลายเป็นเรื่องใหญ่ทันที การเปลืองหน่วยความจำเพียงหนึ่งไบต์ต่อรายการเท่ากับใช้หน่วยความจำเพิ่มขึ้นกว่า 250 กิกะไบต์ทั้งระบบ ทีมจึงตั้งโจทย์ว่าจะลดขนาดต่อรายการลงอย่างไรโดยไม่ทำให้ประสิทธิภาพแย่ลง

โครงสร้างเดิมประกอบด้วยคีย์ที่เก็บชื่อโดเมน ชนิดของคำถาม แฟล็กการยืนยันตัวตน และแท็ก ส่วนตัวรายการเก็บเวลาประทับ อายุของข้อมูล ตัวนับการถูกเรียกใช้ รายการเรกคอร์ดสามชุดแยกกัน และข้อมูลข้อผิดพลาด ปัญหาคือโครงสร้างนี้ใช้คอลเลกชันมาตรฐานของภาษาที่ออกแบบมาสำหรับข้อมูลที่แก้ไขได้ ทั้งที่ข้อมูลในแคชไม่เคยถูกแก้หลังบันทึกแล้ว

ห้าการเปลี่ยนแปลงที่ทำทีละขั้น

ขั้นแรกคือเปลี่ยนจากรายการแบบขยายได้เป็นรายการขนาดคงที่ เพราะคำตอบ DNS ไม่เคยเปลี่ยนหลังถูกแคช โครงสร้างแบบขยายได้จึงเปลืองพื้นที่ไปกับฟิลด์ความจุที่ไม่มีวันได้ใช้ บวกกับการจองหน่วยความจำเผื่อไว้เกินจำเป็น เฉพาะขั้นนี้ประหยัดได้ราว 15 เทระไบต์

ขั้นที่สองคือรวมรายการเรกคอร์ดสามชุดให้เหลือชุดเดียวที่ต่อเนื่องกัน แล้วใช้ตัวเลขบอกตำแหน่งขนาด 2 ไบต์สองตัวเป็นเส้นแบ่งส่วน แทนที่จะเก็บคู่ตัวชี้กับความยาวสามชุด ผลคือลดข้อมูลกำกับจาก 48 ไบต์เหลือ 4 ไบต์ ขั้นที่สามคือเลิกเก็บชื่อเจ้าของเรกคอร์ดซ้ำ เพราะส่วนใหญ่ตรงกับชื่อโดเมนที่ถามอยู่แล้ว จึงอนุมานจากคีย์ตอนอ่านได้ และเก็บเฉพาะกรณีที่ต่างออกไป

ภาพประกอบบทความหมวดคลาวด์
ภาพประกอบบทความหมวดคลาวด์

ขั้นที่ได้ผลที่สุดและบทเรียนเรื่องการแลกได้แลกเสีย

ขั้นที่สี่คือแก้ปัญหาที่ชนิดข้อมูลแบบเลือกได้หลายแบบถูกจองขนาดตามตัวที่ใหญ่ที่สุดเสมอ ทำให้เรกคอร์ดชนิดที่ใช้บ่อยที่สุดต้องแบกพื้นที่ว่างไปด้วยกว่า 120 ไบต์ วิธีแก้แรกคือย้ายตัวแปรใหญ่ ๆ ไปไว้บนฮีปแยก แต่กลับเจอผลข้างเคียงคือภาระของตัวจัดสรรหน่วยความจำเพิ่มขึ้นและข้อมูลกระจัดกระจายจนซีพียูอ่านช้าลง

ขั้นที่ห้าซึ่งให้ผลดีที่สุดคือเก็บข้อมูลเรกคอร์ดเป็นไบต์ดิบตามรูปแบบที่ใช้ส่งบนสายจริง รวมไว้ในบัฟเฟอร์เดียวที่ต่อเนื่องกันโดยมีตัวเลขบอกความยาวนำหน้าแต่ละชิ้น วิธีนี้ตัดทั้งภาระของชนิดข้อมูลแบบเลือกได้และการจองหน่วยความจำแยกก้อนออกไปพร้อมกัน อีกทั้งยังทำให้ข้อมูลอยู่ติดกันจนซีพียูอ่านได้เร็วขึ้น โดยเรกคอร์ดที่ต้องบีบอัดชื่อโดเมนยังคงถูกแปลงตอนอ่าน ส่วนที่เหลือคัดลอกไปใส่คำตอบได้ตรง ๆ

ผลลัพธ์ที่วัดได้จริง

ขนาดต่อรายการลดจาก 953 ไบต์เหลือ 420 ไบต์ คิดเป็นการลดลง 56% ส่วนการจองหน่วยความจำต่อรายการลดจาก 1.1 กิโลไบต์เหลือ 461 ไบต์ หรือลดลง 58% เมื่อวัดในระบบจริง หน่วยความจำที่ใช้อยู่จริงของอินสแตนซ์ที่เปอร์เซ็นไทล์ 99 ลดจาก 9.3 กิกะไบต์เหลือ 5.3 กิกะไบต์ และรวมทั้งฟลีตประหยัดได้ราว 100 เทระไบต์

สิ่งที่ทำให้กรณีนี้น่าสนใจเป็นพิเศษคือไม่ได้แลกความเร็วเพื่อพื้นที่ แต่ได้ทั้งสองอย่าง อัตราการบันทึกลงแคชเพิ่มขึ้น 43% จาก 625,000 เป็น 893,000 รายการต่อวินาที และความหน่วงในการค้นหาลดลง 19% จาก 828 เหลือ 670 นาโนวินาที

ภาพประกอบบทความหมวดคลาวด์
ภาพประกอบบทความหมวดคลาวด์

บทเรียนที่ทีมไทยนำไปใช้ได้

บทเรียนข้อแรกคือต้องวัดก่อนแก้ ทีมสร้างตัวห่อหุ้มตัวจัดสรรหน่วยความจำขึ้นมาเองเพื่อนับการจองต่อรายการควบคู่กับตัวชี้วัดประสิทธิภาพ ซึ่งเป็นสิ่งที่ทำให้รู้ว่าการเปลี่ยนแต่ละขั้นได้ผลจริงหรือไม่ ข้อที่สองคือผลจากการทดสอบในห้องกับผลในระบบจริงต่างกันเสมอ ตัวเลข 56% จากการวัดต่อรายการกลายเป็น 42-43% เมื่อวัดหน่วยความจำจริงของเครื่อง เพราะมีภาระอื่นที่การทดสอบสังเคราะห์ไม่ครอบคลุม

ข้อที่สามคือปรับทีละขั้นดีกว่ารื้อใหญ่ครั้งเดียว การแบ่งเป็นห้าขั้นทำให้วัดผลระหว่างทางได้และย้อนกลับได้เมื่อขั้นใดให้ผลแย่ลง ซึ่งเกิดขึ้นจริงในขั้นที่สี่ และข้อสุดท้ายคือปรับให้เหมาะกับกรณีที่พบบ่อยที่สุด การเลือกปรับให้เข้ากับเรกคอร์ด 80% ที่คัดลอกตรงได้ ให้ผลตอบแทนมากกว่าการพยายามทำให้ทุกกรณีดีเท่ากัน สำหรับทีมไทยที่ดูแลระบบซึ่งเก็บข้อมูลจำนวนมากในหน่วยความจำ เช่น แคชของ API หรือคิวงาน หลักคิดชุดนี้ใช้ได้ตรง ๆ แม้จะไม่ได้ทำงานที่สเกลระดับเดียวกัน

สรุปสาระสำคัญ

  • โจทย์: หนึ่งไบต์ที่คูณด้วย 250,000 ล้าน
  • ห้าการเปลี่ยนแปลงที่ทำทีละขั้น
  • ขั้นที่ได้ผลที่สุดและบทเรียนเรื่องการแลกได้แลกเสีย
แหล่งอ้างอิงเรียบเรียงจาก Cloudflare Blog — How we saved 100 terabytes of memory by optimizing 1.1.1.1's DNS cache — อ่านบทความต้นฉบับ
ภาพปก: Cloudflare Blog · ลิขสิทธิ์ภาพเป็นของเจ้าของต้นฉบับ ใช้ประกอบการรายงานพร้อมอ้างอิงแหล่งที่มา
มีคำถามเพิ่มเติมเกี่ยวกับบทความนี้? เขียนหาเราได้ที่ info@smart-cyber-tech.com
บริการที่เกี่ยวข้องจากทีมงาน Smart Cyber Tech

บทความอื่นที่เกี่ยวข้อง

บทความที่เกี่ยวข้อง

ลดค่าใช้จ่ายคลาวด์อย่างเป็นระบบตามแนวทาง AWS Well-Architected คลาวด์

ลดค่าใช้จ่ายคลาวด์อย่างเป็นระบบตามแนวทาง AWS Well-Architected

องค์กรจำนวนมากจ่ายค่าคลาวด์เกินจำเป็น 20-30% จากทรัพยากรที่ไม่ได้ใช้และขนาดที่ใหญ่เกินงาน บทความนี้สรุปหลักการจาก Cost Optimization Pillar ของ AWS Well-Architected Framework ตั้งแต่การมองเห็นค่าใช้จ่าย การเลือกโมเดลราคา ไปจนถึงการสร้างวัฒนธรรม FinOps ในทีม

อ่านบทความ
กันเส้นทางอินเทอร์เน็ตรั่วด้วย BGP Roles: มาตรฐาน RFC 9234 คืออะไรและใครใช้แล้วบ้าง คลาวด์

กันเส้นทางอินเทอร์เน็ตรั่วด้วย BGP Roles: มาตรฐาน RFC 9234 คืออะไรและใครใช้แล้วบ้าง

เหตุการณ์ทราฟฟิกอินเทอร์เน็ตวิ่งผิดเส้นทางจนบริการล่มเป็นวงกว้างเกิดขึ้นซ้ำ ๆ มาหลายปี มาตรฐาน RFC 9234 พยายามแก้ที่ต้นเหตุด้วยการให้เราเตอร์ตกลงบทบาทกันตั้งแต่เริ่มเชื่อมต่อ บทความนี้สรุปว่ามันทำงานอย่างไรและการนำไปใช้จริงติดตรงไหน

อ่านบทความ
Cloudflare ฉบับเริ่มต้น: เข้าใจ DNS, Cache, WAF และ Workers ใน 10 นาที คลาวด์

Cloudflare ฉบับเริ่มต้น: เข้าใจ DNS, Cache, WAF และ Workers ใน 10 นาที

Cloudflare กลายเป็นชั้นหน้าบ้านของเว็บจำนวนมากทั่วโลก แต่เมนูตั้งค่าหลายร้อยรายการทำให้ผู้เริ่มต้นถอดใจ บทความนี้สรุปแนวคิดหลักจากเอกสารทางการของ Cloudflare อธิบาย DNS, Proxy, Cache, WAF และ Workers ด้วยภาษาที่เข้าใจง่าย พร้อมคำแนะนำว่าเว็บแบบไหนควรใช้หรือยังไม่จำเป็น

อ่านบทความ

ติดต่อเพื่อขอรับคำปรึกษาจากทีมงาน

ตั้งแต่ประเมินระบบปัจจุบัน วางแผน จนถึงลงมือพัฒนา — คุยกับเราได้โดยไม่มีค่าใช้จ่าย

ปรึกษาทีมของเรา