• เมื่อ Netflix ขยายไปยังหลากหลายโดเมน เช่น VoD และ Gaming ความสามารถในการจัดเก็บและประมวลผลข้อมูลตามเวลาในปริมาณมหาศาลระดับเพตะไบต์ด้วยค่าหน่วงระดับมิลลิวินาทีจึงกลายเป็นสิ่งสำคัญ
  • Netflix ได้พัฒนา TimeSeries abstraction บนพื้นฐานของ Key-Value abstraction และแพลตฟอร์ม Data Gateway เพื่อมอบโซลูชันที่สามารถจัดเก็บและคิวรีข้อมูลเหตุการณ์ตามเวลาได้อย่างมีประสิทธิภาพในหลากหลายกรณีการใช้งาน

ความท้าทาย

  • ที่ Netflix มีการสร้างและใช้งานข้อมูลตามเวลาอย่างต่อเนื่องจากการโต้ตอบของผู้ใช้ การแสดงผลแอสเซ็ต และกิจกรรมของเครือข่ายไมโครเซอร์วิสที่ซับซ้อน
  • การจัดการข้อมูลเหล่านี้อย่างมีประสิทธิภาพมีความสำคัญต่อการรับประกันประสบการณ์ผู้ใช้และความน่าเชื่อถือของระบบ
  • ความท้าทายหลัก:
    • ปริมาณงานสูง: ต้องรองรับการเขียนได้สูงสุด 10 ล้านรายการต่อวินาที พร้อมรักษาความพร้อมใช้งานในระดับสูง
    • คิวรีอย่างมีประสิทธิภาพบนชุดข้อมูลขนาดใหญ่: ต้องจัดเก็บข้อมูลระดับเพตะไบต์ พร้อมคืนผลการอ่านด้วย primary key ในระดับมิลลิวินาทีต่ำ และรองรับการค้นหาและการรวมผลผ่านคุณสมบัติรองหลายแบบ
    • การอ่านและเขียนแบบทั่วโลก: รองรับการอ่านและเขียนจากที่ใดก็ได้ทั่วโลก พร้อมมีโมเดลความสอดคล้องที่ปรับได้
    • การกำหนดค่าที่ปรับได้: รองรับความสามารถในการแบ่งชุดข้อมูลบน data store แบบผู้เช่าเดี่ยวหรือหลายผู้เช่า
    • การจัดการ burst traffic: ต้องรับมือกับทราฟฟิกที่พุ่งสูงขึ้นจากการเปิดตัวคอนเทนต์ใหม่หรือการกู้คืนจากเหตุขัดข้องระดับภูมิภาค
    • ความคุ้มค่าด้านต้นทุน: ต้องลดต้นทุนโครงสร้างพื้นฐานให้ต่ำที่สุด พร้อมเพิ่มประสิทธิภาพการเก็บรักษาระยะยาว

TimeSeries abstraction

  • การแบ่งข้อมูล: ใช้กลยุทธ์การแบ่งตามเวลาเฉพาะตัวและแนวทาง event bucket เพื่อจัดการเวิร์กโหลดแบบ burst ได้อย่างมีประสิทธิภาพและทำให้คิวรีง่ายขึ้น
  • สตอเรจที่ยืดหยุ่น: ออกแบบให้เชื่อมต่อกับสตอเรจแบ็กเอนด์ได้หลากหลาย เช่น Apache Cassandra และ Elasticsearch
  • ความสามารถในการกำหนดค่า: มีตัวเลือกที่ปรับแต่งได้หลากหลายสำหรับแต่ละ dataset เพื่อให้ยืดหยุ่นต่อกรณีการใช้งานที่แตกต่างกัน
  • การขยายระบบ: รองรับทั้งการขยายแนวนอนและแนวตั้ง เพื่อรองรับ throughput และปริมาณข้อมูลที่เพิ่มขึ้นตามการเติบโตของฐานผู้ใช้และบริการของ Netflix
  • โครงสร้างพื้นฐานแบบ shard: ใช้ Data Gateway Platform เพื่อปรับใช้โครงสร้างพื้นฐานแบบผู้เช่าเดี่ยวและ/หรือหลายผู้เช่า พร้อมการแยกการเข้าถึงและทราฟฟิกตามต้องการ

โมเดลข้อมูล

  • ใช้โมเดลข้อมูลเหตุการณ์เฉพาะตัวที่ห่อหุ้มข้อมูลเหตุการณ์ไว้เพื่อให้คิวรีได้อย่างมีประสิทธิภาพ
  • Event item: event item คือคู่คีย์-ค่าที่ผู้ใช้ใช้เก็บข้อมูลของเหตุการณ์หนึ่ง ๆ ตัวอย่าง: {"device_type": "ios"}
  • Event: event คือคอลเลกชันแบบมีโครงสร้างที่ประกอบด้วย event item หนึ่งรายการขึ้นไป โดย event จะเกิดขึ้น ณ เวลาหนึ่ง และระบุด้วย timestamp ที่สร้างจากไคลเอนต์และตัวระบุเหตุการณ์ (เช่น UUID) การรวมกันของ event_time และ event_id จะเป็นส่วนหนึ่งของ idempotency key ที่ไม่ซ้ำกันของ event ทำให้ผู้ใช้สามารถ retry request ได้อย่างปลอดภัย
  • TimeSeries ID: time_series_id คือชุดของเหตุการณ์ตั้งแต่หนึ่งรายการขึ้นไปที่เกิดขึ้นภายในช่วงการเก็บรักษาของ dataset เช่น device_id อาจเก็บเหตุการณ์ทั้งหมดที่เกิดขึ้นบนอุปกรณ์หนึ่งเครื่องในช่วงเวลาการเก็บรักษา ทุก event เป็น immutable และบริการ TimeSeries จะทำเพียง append event เข้าไปใน time series ID ที่กำหนด
  • Namespace: namespace คือชุดของ time series ID และข้อมูล event ซึ่งแทน dataset ของ TimeSeries ทั้งหมด ผู้ใช้สามารถสร้างได้ตั้งแต่หนึ่ง namespace ขึ้นไปสำหรับแต่ละ use case และ abstraction นี้จะใช้ตัวเลือกการปรับแต่งต่าง ๆ ในระดับ namespace

API

  • WriteEventRecordsSync: endpoint นี้เขียน batch ของ event และส่งการยืนยันความคงทนกลับไปยังไคลเอนต์ ใช้เมื่อผู้ใช้ต้องการการรับประกันด้าน durability
  • WriteEventRecords: นี่คือเวอร์ชัน fire-and-forget ของ endpoint ข้างต้น โดยจะนำ batch ของ event เข้า queue โดยไม่มีการยืนยันความคงทน ใช้ในกรณีอย่าง logging หรือ tracing ที่ผู้ใช้ให้ความสำคัญกับ throughput มากกว่าและยอมรับการสูญหายของข้อมูลได้เล็กน้อย
  • ReadEventRecords: เมื่อระบุ namespace, timeSeriesId, timeInterval และ eventFilters แบบเลือกได้ endpoint นี้จะคืน event ที่ตรงกันทั้งหมดโดยเรียงตาม event_time แบบลดหลั่น พร้อมค่าหน่วงต่ำระดับมิลลิวินาที
  • SearchEventRecords: เมื่อให้เกณฑ์การค้นหาและช่วงเวลา endpoint นี้จะคืน event ที่ตรงกันทั้งหมด กรณีใช้งานลักษณะนี้เหมาะกับการอ่านแบบ eventually consistent
  • AggregateEventRecords: เมื่อให้เกณฑ์การค้นหาและโหมดการรวมผล (เช่น DistinctAggregation) endpoint นี้จะทำการรวมผลที่กำหนดภายในช่วงเวลาที่ระบุ คล้ายกับ Search endpoint ผู้ใช้ต้องยอมรับ eventual consistency และอาจมีค่าหน่วงสูงกว่าในระดับวินาที

ชั้นสตอเรจ

  • ชั้นสตอเรจของ TimeSeries ประกอบด้วย data store หลักและ data store สำหรับดัชนีที่เป็นทางเลือก
  • Apache Cassandra เป็นตัวเลือกหลักสำหรับ data store ที่รับประกัน durability ในสถานการณ์ที่มี throughput สูง
  • Elasticsearch เป็นตัวเลือกหลักสำหรับ data store ด้าน indexing

data store หลัก

  • ใช้ Apache Cassandra เพื่อรองรับกรณีการใช้งานของ TimeSeries
  • จัดการข้อมูลด้วย Temporal Partitioning ที่แบ่งข้อมูลออกเป็นชิ้นตามช่วงเวลา
    • time slice: แมปกับตาราง Cassandra ที่สอดคล้องกับช่วงการเก็บรักษา
    • time bucket: แบ่งข้อมูลซ้ำภายใน time slice เพื่อเพิ่มประสิทธิภาพของคิวรีตามช่วงเวลาเฉพาะ
    • event bucket: แบ่งซ้ำ time bucket เพื่อรองรับการเขียนจำนวนมากใน time series ภายในช่วงเวลาสั้น ๆ
  • ตารางข้อมูลใช้เก็บข้อมูล event จริง ส่วนตาราง metadata ใช้เก็บข้อมูลการตั้งค่า time slice แยกตาม namespace

data store สำหรับดัชนี

  • ข้อมูลจะถูกทำดัชนีลงใน Elasticsearch เพื่อรองรับรูปแบบการเข้าถึงรองผ่านคุณสมบัติที่ไม่ใช่ primary key
  • ผู้ใช้สามารถกำหนดรายการคุณสมบัติสำหรับการค้นหาและการรวมผลแยกตาม namespace ได้

Control plane

  • data plane รับผิดชอบงานอ่าน/เขียน ส่วน control plane รับผิดชอบการกำหนดค่าทุกด้านของพฤติกรรม namespace
  • data plane สื่อสารกับ TimeSeries control stack ซึ่งโต้ตอบกับ Data Gateway control plane
  • การตั้งค่า namespace ช่วยให้ปรับแต่งสิ่งต่าง ๆ ได้อย่างยืดหยุ่น เช่น การแบ่งตามเวลา การบัฟเฟอร์ ความสอดคล้อง และการเก็บรักษา

การตั้งค่า namespace

  • สามารถปรับแต่งหลายอย่างในระดับ namespace ผ่าน configuration snippet ที่แสดงให้เห็นถึงความยืดหยุ่นของบริการ

Infrastructure provisioning

  • ระบบจะหาการตั้งค่าที่เหมาะสมที่สุดผ่านเวิร์กโฟลว์ provisioning แบบอัตโนมัติ โดยพิจารณาจากพารามิเตอร์ที่หลากหลาย
  • หลังจาก provisioning โครงสร้างพื้นฐานเริ่มต้นแล้ว ระบบจะขยายต่อไปตามเวิร์กโหลดของผู้ใช้

การขยายระบบ

  • เนื่องจากการคาดการณ์การใช้งานในช่วง provisioning เริ่มต้นมีข้อจำกัด จึงจำเป็นต้องมีการปรับหลังจากใช้งานจริง
  • การขยายแนวนอน: อินสแตนซ์เซิร์ฟเวอร์ TimeSeries สามารถขยายขึ้นและลดลงโดยอัตโนมัติตามความต้องการทราฟฟิก
  • การขยายแนวตั้ง: สามารถขยายอินสแตนซ์เซิร์ฟเวอร์ TimeSeries หรืออินสแตนซ์สตอเรจในแนวตั้ง เพื่อให้ได้ CPU, RAM และ/หรือความจุสตอเรจที่เชื่อมต่อมากขึ้น
  • การขยายดิสก์: สามารถเชื่อมต่อ EBS เพื่อเก็บข้อมูลได้ และเมื่อพื้นที่ดิสก์ถึงเกณฑ์ที่กำหนด ระบบจะขยาย EBS volume
  • ปรับ dataset ที่ถูกแบ่งมากเกินไปหรือน้อยเกินไปผ่านการ repartition ข้อมูล

หลักการออกแบบ

  • Event idempotency: สร้าง idempotency ไว้ในทุก mutation endpoint เพื่อให้ผู้ใช้ retry request ได้อย่างปลอดภัย
  • SLO-based hedging: กำหนดเป้าหมาย Service Level Objective (SLO) สำหรับ endpoint หลายประเภทเพื่อรับประกันประสิทธิภาพ
  • Partial return: หากไคลเอนต์ไวต่อค่าหน่วง ก็สามารถรับชุดผลลัพธ์บางส่วนได้
  • Adaptive pagination: หากชั้นบริการพิจารณาว่า dataset ของ time series มีความหนาแน่น ก็จะปรับ fanout factor แบบไดนามิก
  • หน้าต่างการเขียนที่จำกัด: ทำให้ข้อมูลกลายเป็น immutable ให้เร็วที่สุดเท่าที่จะทำได้ เพื่อให้สามารถใช้การเพิ่มประสิทธิภาพต่าง ๆ ได้
  • การบัฟเฟอร์การเขียน: เพื่อรองรับเวิร์กโหลดแบบ burst ระบบจะรวม event เข้าด้วยกันในช่วงเวลาสั้น ๆ เพื่อกระจายโหลดให้สม่ำเสมอ
  • การบีบอัดแบบไดนามิก: เมื่อข้อมูลกลายเป็น immutable แล้ว จะใช้กลยุทธ์การบีบอัดเพื่อเพิ่มประสิทธิภาพการอ่าน

ประสิทธิภาพจริง

  • บริการนี้สามารถบันทึกข้อมูลได้ด้วยค่าหน่วงต่ำระดับมิลลิวินาที พร้อมรักษาค่าหน่วงของ point read ให้คงที่

การใช้งาน Time Series ภายใน Netflix

TimeSeries abstraction มีบทบาทสำคัญในบริการหลักของ Netflix ตัวอย่าง use case ที่มีอิทธิพลมีดังนี้

  • การติดตามและข้อมูลเชิงลึก: ทำ log tracing ครอบคลุมทุกแอปและไมโครเซอร์วิสภายใน Netflix เพื่อทำความเข้าใจการสื่อสารระหว่างบริการ ช่วยดีบักปัญหา และตอบคำขอสนับสนุน
  • การติดตามปฏิสัมพันธ์ของผู้ใช้: ติดตามการโต้ตอบของผู้ใช้หลายล้านครั้ง เช่น การเล่นวิดีโอ การค้นหา และการมีส่วนร่วมกับคอนเทนต์ เพื่อปรับปรุงอัลกอริทึมการแนะนำของ Netflix แบบเรียลไทม์ และมอบข้อมูลเชิงลึกเพื่อยกระดับประสบการณ์ผู้ใช้โดยรวม
  • การเปิดตัวฟีเจอร์และการวิเคราะห์ประสิทธิภาพ: ติดตามการเปิดตัวและประสิทธิภาพของฟีเจอร์ผลิตภัณฑ์ใหม่ ช่วยให้วิศวกรของ Netflix วัดได้ว่าผู้ใช้โต้ตอบกับฟีเจอร์อย่างไร และสนับสนุนการตัดสินใจปรับปรุงในอนาคตบนฐานข้อมูล
  • การติดตามและเพิ่มประสิทธิภาพ asset impression: ติดตามการแสดงผลของแอสเซ็ตเพื่อให้มั่นใจว่าคอนเทนต์และแอสเซ็ตถูกส่งมอบอย่างมีประสิทธิภาพ พร้อมให้ feedback แบบเรียลไทม์เพื่อการปรับให้เหมาะสม
  • การเรียกเก็บเงินและการจัดการการสมัครสมาชิก: จัดเก็บข้อมูลย้อนหลังที่เกี่ยวข้องกับการเรียกเก็บเงินและการจัดการการสมัครสมาชิก เพื่อรับประกันความถูกต้องของประวัติธุรกรรมและสนับสนุนการสอบถามจากฝ่ายบริการลูกค้า

การปรับปรุงในอนาคต

เมื่อ use case มีการเปลี่ยนแปลงและความจำเป็นในการทำ abstraction ให้คุ้มค่าด้านต้นทุนมากขึ้นเพิ่มสูงขึ้น Netflix วางแผนจะปรับปรุงบริการนี้อย่างมากในอีกไม่กี่เดือนข้างหน้า บางส่วนมีดังนี้

  • Tiered storage เพื่อประสิทธิภาพด้านต้นทุน: รองรับการย้ายข้อมูลที่เก่ากว่าและถูกเข้าถึงน้อยไปยัง object storage ที่มีราคาถูกกว่าแต่ใช้เวลานานกว่าจะถึง first byte ซึ่งอาจช่วยประหยัดค่าใช้จ่ายให้ Netflix ได้หลายล้านดอลลาร์
  • Dynamic event bucketing: แทนที่จะใช้การตั้งค่าที่ค่อนข้างคงที่ขณะ provisioning namespace ระบบจะรองรับการแบ่งคีย์แบบเรียลไทม์ไปยังพาร์ทิชันขนาดที่เหมาะสมที่สุดขณะ event ไหลเข้ามาแบบสตรีมมิง กลยุทธ์นี้มีข้อดีสำคัญคือช่วยลดต้นทุนรวมของ read amplification ด้วยการ ไม่ แบ่งพาร์ทิชันให้กับ time_series_id ที่ ไม่จำเป็นต้อง แบ่งพาร์ทิชัน นอกจากนี้ใน Cassandra 4.x ยังมีการปรับปรุงสำคัญสำหรับการอ่านชุดย่อยของข้อมูลจากพาร์ทิชันขนาดใหญ่ จึงอาจลดความจำเป็นในการแบ่งชุดข้อมูลทั้งหมดแบบเชิงรุกล่วงหน้า
  • Caching: ใช้ประโยชน์จากความเป็น immutable ของข้อมูลเพื่อแคชแต่ละช่วงเวลาอย่างชาญฉลาด
  • การนับและการรวมผลอื่น ๆ: ผู้ใช้บางรายสนใจเพียงจำนวน event ภายในช่วงเวลาที่กำหนด แทนที่จะดึงข้อมูล event ทั้งหมด

บทสรุป

  • TimeSeries Abstraction เป็นองค์ประกอบสำคัญของโครงสร้างพื้นฐานข้อมูลออนไลน์ของ Netflix โดยรองรับทั้งการตัดสินใจแบบเรียลไทม์และระยะยาว
  • เมื่อ Netflix ขยายไปยังโดเมนใหม่ ๆ TimeSeries Abstraction จะยังคงเป็นองค์ประกอบหลักของแพลตฟอร์มและช่วยขยายขีดความสามารถของการสตรีมและสิ่งที่มากกว่านั้น

ความเห็นของ GN⁺

  • ความเชี่ยวชาญของ Netflix ในการประมวลผลข้อมูลอนุกรมเวลาปริมาณมหาศาลอย่างเสถียรผ่าน TimeSeries abstraction นั้นน่าประทับใจ เพราะสามารถได้ทั้งความสามารถในการขยายระบบ ความยืดหยุ่น และความคุ้มค่าด้านต้นทุนไปพร้อมกัน โดยเฉพาะเทคนิคที่ปรับให้เหมาะกับลักษณะข้อมูลและรูปแบบการเข้าถึง เช่น time-based partitioning, write buffering และ dynamic compaction ที่โดดเด่นมาก
  • สิ่งนี้ไม่ใช่เพียง time-series DB ธรรมดา แต่เป็นชั้น abstraction ที่ช่วยให้ใช้สตอเรจอย่าง Cassandra และ Elasticsearch ได้อย่างยืดหยุ่น พร้อมมีระบบควบคุมสำหรับ provisioning และปฏิบัติการโครงสร้างพื้นฐานให้เหมาะกับลักษณะเวิร์กโหลด ทำให้ผู้ใช้สามารถซ่อนความซับซ้อนและโฟกัสกับข้อมูลได้
  • ปัจจุบันระบบรองรับข้อมูลระดับเพตะไบต์และประมวลผลได้ 15 ล้าน event ต่อวินาที จึงนับเป็นตัวอย่างที่น่าเรียนรู้สำหรับองค์กรที่ต้องการสร้างไปป์ไลน์ข้อมูลอนุกรมเวลาประสิทธิภาพสูง โดยชี้ให้เห็นว่า สำหรับบริการขนาดใหญ่ต้องคำนึงถึงทั้งปริมาณและความเร็วของข้อมูล รวมถึงต้นทุนอย่างรอบด้าน
  • ระบบนี้ถูกใช้งานอย่างหลากหลายในพื้นที่สำคัญของธุรกิจ Netflix เช่น tracing การวิเคราะห์พฤติกรรมผู้ใช้ และการจัดการการเรียกเก็บเงิน แสดงให้เห็นว่าข้อมูลอนุกรมเวลาเป็นแรงขับเคลื่อนของการตัดสินใจบนฐานข้อมูลและนวัตกรรมบริการ ไม่ได้เป็นเพียงการทำ logging แต่ยังเป็นรากฐานของบริการที่อิง ML/AI เช่นระบบแนะนำแบบเรียลไทม์
  • แผนการพัฒนาในอนาคต เช่น tiered storage, dynamic partitioning และการรวมผลรูปแบบต่าง ๆ สะท้อนให้เห็นถึงความตั้งใจในการพัฒนาอย่างต่อเนื่อง เพื่อตอบสนองต่อความต้องการทางธุรกิจที่เปลี่ยนแปลงรวดเร็ว และหวังว่าความรู้ที่สั่งสมระหว่างทางจะถูกแบ่งปันผ่านโอเพนซอร์สหรือช่องทางอื่น ๆ

ยังไม่มีความคิดเห็น

ยังไม่มีความคิดเห็น