คอร์สพื้นฐานการสัมภาษณ์ออกแบบระบบ
คอร์สที่มีโครงสร้างครอบคลุมแผนการสัมภาษณ์ การประมาณความจุ การขยายระบบ ฐานข้อมูล API ไมโครเซอร์วิส ความน่าเชื่อถือ การสังเกตการณ์ และความปลอดภัย พร้อมข้อสอบที่เชื่อมโยง
สิ่งที่คุณจะได้เรียนรู้
- อธิบายแผนการสัมภาษณ์ออกแบบระบบและทำความเข้าใจความต้องการ
- ประมาณ QPS พื้นที่จัดเก็บ และความจุด้วยการคำนวณง่าย
- ใช้ load balancing แคช และ CDN เพื่อขยายบริการ
- เปรียบเทียบฐานข้อมูล sharding และความสอดคล้องด้วย CAP
- ออกแบบ API ไมโครเซอร์วิส คิว และระบบที่เชื่อถือได้และสังเกตได้
ก่อนเริ่มเรียน
- ความรู้พื้นฐานการเขียนโปรแกรม
- คุ้นเคยกับ HTTP API และฐานข้อมูล
- ไม่จำเป็นต้องมีประสบการณ์สัมภาษณ์ออกแบบระบบมาก่อน
บทเรียน 1 แผนการสัมภาษณ์ออกแบบระบบ
การสัมภาษณ์ออกแบบระบบทดสอบวิธีเปลี่ยนแนวคิดผลิตภัณฑ์ให้เป็นแผนเทคนิคที่ชัดเจน ผู้สัมภาษณ์ต้องการเห็นโครงสร้าง การสื่อสาร และการตระหนักถึงข้อแลกเปลี่ยน ไม่ใช่สถาปัตยกรรมที่ท่องจำ เริ่มต้นด้วยการทวนปัญหาและถามเกี่ยวกับผู้ใช้ ขนาด และข้อจำกัด
ขั้นแรกทำความเข้าใจความต้องการ: ใครใช้ระบบ มีการอ่านและเขียนกี่ครั้งต่อวินาที ต้องการความหน่วงเท่าใด ต้องเก็บข้อมูลเท่าไร และผู้ใช้อยู่ในภูมิภาคใด จดตัวเลขเหล่านี้ไว้เพราะการตัดสินใจต่อไปทั้งหมดขึ้นอยู่กับมัน
ถัดไปทำการประมาณความจุอย่างง่าย ประมาณผู้ใช้รายวัน จำนวนคำขอต่อวินาที การเติบโตของพื้นที่จัดเก็บ และแบนด์วิดท์ การคำนวณคร่าว ๆ เช่น QPS = DAU x จำนวนการกระทำต่อวัน / วินาที เพียงพอต่อการเลือกขนาดของระบบ
จากนั้นวาดการออกแบบระดับสูง: ไคลเอนต์ ตัวกระจายโหลด บริการแอปพลิเคชัน แคช คิว และฐานข้อมูล ระบุชื่อแต่ละส่วนและอธิบายเส้นทางคำขอหลักก่อนลงรายละเอียด
เลือกหนึ่งหรือสองส่วนเพื่อเจาะลึก เช่น โมเดลข้อมูล การออกแบบ API กลยุทธ์ sharding หรือการจัดการความล้มเหลว ระบุข้อแลกเปลี่ยนที่ต้องการและเปรียบเทียบอย่างน้อยหนึ่งทางเลือกก่อนตัดสินใจ
ปิดท้ายด้วยสรุปสั้น ๆ: ส่วนประกอบหลัก ความเสี่ยงหลัก และสิ่งที่ต้องมอนิเตอร์ การสรุปที่ชัดเจนช่วยให้ผู้สัมภาษณ์เข้าใจวิธีคิดของคุณ
เคล็ดลับฝึกฝน แผนการสัมภาษณ์ออกแบบระบบ: ทบทวนบทเรียนนี้ในเวลาสั้น ๆ ทุกวัน หลังทำแบบฝึกหัดแต่ละข้อให้บอกกฎหรือขั้นตอนที่ใช้ ถ้าบอกไม่ได้ ให้ทบทวนหัวข้อนั้นก่อนไปต่อ ความสม่ำเสมอช่วยจำได้ดีกว่าการอ่านนาน ๆ ครั้งเดียว
ตัวอย่าง
โจทย์: "ออกแบบระบบย่อ URL" เริ่มจากความต้องการ: ผู้ใช้ จำนวนลิงก์ที่สร้างต่อวัน การอ่านต่อลิงก์ พื้นที่จัดเก็บ และวันหมดอายุ จากนั้นอธิบายขั้นตอนหลัก: ไคลเอนต์ส่ง URL ยาว บริการสร้าง ID สั้น เก็บการแมป และเปลี่ยนเส้นทางการอ่านด้วย 301 หรือ 302
ตัวอย่างคำตอบ: QPS = 1 ล้านลิงก์/วัน / 86,400 วินาที ≈ 12 การเขียน/วินาที โดยการอ่านมากกว่าประมาณ 100 เท่า อัตราการเขียนที่ต่ำเหมาะกับฐานข้อมูลเชิงสัมพันธ์ ส่วนการอ่านควรใช้แคชและ CDN
อ่านคำถามอีกครั้งก่อนจบ และตรวจสอบว่าคำตอบตรงกับสิ่งที่ถาม
บทเรียน 2 การขยายระบบ การกระจายโหลด และแคช
การขยายระบบเป็นสิ่งแรกที่มักถูกทดสอบเพราะเชื่อมทุกส่วนเข้าด้วยกัน การขยายแนวดิ่งเพิ่มพลังให้เครื่องเดียว การขยายแนวนอนเพิ่มเครื่องหลายเครื่องและเป็นตัวเลือกทั่วไปสำหรับระบบเว็บ
ตัวกระจายโหลดอยู่หน้าบริการ ตรวจสอบสถานะ และกระจายทราฟฟิกด้วยกลยุทธ์เช่น round-robin หรือ least connections ตัวกระจายโหลดชั้น 7 ยังแบ่งตาม path URL และ header ได้
แคชเก็บข้อมูลที่อ่านบ่อยไว้ใกล้ผู้เรียก สำหรับการอ่านฐานข้อมูลให้ใช้ cache-aside: ตรวจแคช โหลดจากฐานข้อมูลเมื่อไม่พบ เขียนกลับ และตั้ง TTL เลือกการไล่ LRU และกำหนดเวลาที่ต้อง invalidate
CDN ให้บริการไฟล์สถิตจากจุดให้บริการใกล้ผู้ใช้ ลดความหน่วงทั่วโลก เหมาะกับรูปภาพ JavaScript CSS และเนื้อหาที่ไม่เปลี่ยนแปลง
สำหรับ hot keys รายการยอดนิยมหนึ่งรายการอาจทำให้ shard แคชหนึ่งหนักเกินไป กระจายคีย์ไปหลาย shard หรือเพิ่มความหลากหลายในคีย์แคช และแคชข้อมูลรวมระดับต่าง ๆ แยกกัน
ตัวอย่าง: feed ที่อ่านหนักสามารถวาง API หลัง load balancer แคช feed ยอดนิยมใน Redis และให้บริการไฟล์สถิตผ่าน CDN
เคล็ดลับฝึกฝน การขยายระบบ การกระจายโหลด และแคช: ทบทวนบทเรียนนี้ในเวลาสั้น ๆ ทุกวัน หลังทำแบบฝึกหัดแต่ละข้อให้บอกกฎหรือขั้นตอนที่ใช้ ถ้าบอกไม่ได้ ให้ทบทวนหัวข้อนั้นก่อนไปต่อ ความสม่ำเสมอช่วยจำได้ดีกว่าการอ่านนาน ๆ ครั้งเดียว
ตัวอย่าง
การตัดสินใจ: ฟีดข่าวมีการอ่าน 10,000 ครั้งต่อวินาที วาง load balancer หน้าเซิร์ฟเวอร์ API แคชฟีดยอดนิยม 1,000 รายการใน Redis และให้บริการรูปโปรไฟล์และรูปภาพผ่าน CDN
คำถามต่อ: "จะเกิดอะไรขึ้นถ้าฟีดหนึ่งร้อนเกินไป" กระจายคีย์แคชไปหลาย shard และเพิ่ม TTL สั้นเพื่อไม่ให้ฐานข้อมูลทำงานหนักเกินไป
อ่านคำถามอีกครั้งก่อนจบ และตรวจสอบว่าคำตอบตรงกับสิ่งที่ถาม
บทเรียน 3 ฐานข้อมูล Sharding และความสอดคล้อง
การเลือกฐานข้อมูลขึ้นอยู่กับรูปแบบการเข้าถึง ฐานข้อมูลเชิงสัมพันธ์เหมาะกับธุรกรรมที่มีโครงสร้างและการ join ฐานข้อมูล NoSQLช่วยเรื่อง schema ยืดหยุ่น ปริมาณการเขียนสูง หรือข้อมูลกระจายขนาดใหญ่
เพิ่มดัชนีสำหรับเส้นทาง query ที่พบบ่อย และทำdenormalizationเมื่อ join มีราคาแพง read replica ย้ายทราฟฟิก SELECT ออกจาก primary และ failover ช่วยให้การเขียนยังใช้งานได้เมื่อ primary ล้มเหลว
Shardingแบ่งแถวตามคีย์ด้วยการแบ่งแบบ range หรือ hash การแบ่งแบบ hash กระจายโหลดสม่ำเสมอแต่ทำให้ query ช่วงยาก การแบ่งแบบ range ช่วย locality แต่อาจเกิด shard ร้อน
ทฤษฎี CAPกล่าวว่าระบบกระจายต้องเลือกระหว่างความสอดคล้องและความพร้อมใช้งานระหว่าง partition ความสอดคล้องแบบ strong เข้าใจง่าย ส่วน eventual consistency ขยายได้ดีกว่าแต่ต้องมีการ reconcile
ธุรกรรมกระจายมีต้นทุนสูง ใช้การดำเนินการ idempotent ตาราง outbox หรือ workflow แบบ event แทนการทำให้ทุกการเขียน atomic ข้ามบริการ
ในการสัมภาษณ์ ให้ระบุฐานข้อมูล คีย์ shard กลยุทธ์ replica และโมเดลความสอดคล้อง การตัดสินใจสี่อย่างนี้แสดงว่าคุณเข้าใจข้อมูลในระดับใหญ่
เคล็ดลับฝึกฝน ฐานข้อมูล Sharding และความสอดคล้อง: ทบทวนบทเรียนนี้ในเวลาสั้น ๆ ทุกวัน หลังทำแบบฝึกหัดแต่ละข้อให้บอกกฎหรือขั้นตอนที่ใช้ ถ้าบอกไม่ได้ ให้ทบทวนหัวข้อนั้นก่อนไปต่อ ความสม่ำเสมอช่วยจำได้ดีกว่าการอ่านนาน ๆ ครั้งเดียว
ตัวอย่าง
การตัดสินใจ: บริการแชทเก็บข้อความตาม conversation_id การ hash sharding บนคีย์นั้นทำให้บทสนทนาหนึ่งอยู่ใน shard เดียว ส่วน index รองรองรับการค้นหากล่องข้อความของผู้ใช้
ความสอดคล้อง: ใช้ strong consistency สำหรับการยืนยันข้อความ และ eventual consistency สำหรับการอ่านแล้ว จากนั้น reconcile ด้วย timestamp
อ่านคำถามอีกครั้งก่อนจบ และตรวจสอบว่าคำตอบตรงกับสิ่งที่ถาม
บทเรียน 4 REST API ไมโครเซอร์วิส และคิวข้อความ
การออกแบบ APIที่สะอาดช่วยให้ระบบสร้างและบำรุงรักษาง่าย REST ใช้ทรัพยากรและ HTTP verb: GET อ่าน POST สร้าง PUT แทนที่ PATCH อัปเดต และ DELETE ลบ ใช้รหัสสถานะเช่น 201 สำหรับ created และ 429 สำหรับถูกจำกัดอัตรา
ใช้paginationสำหรับชุดข้อมูลขนาดใหญ่ cursor pagination มีเสถียรภาพมากกว่าเมื่อข้อมูลเปลี่ยน offset pagination ง่ายกว่าแต่อาจข้ามหรือซ้ำแถว
Rate limitingปกป้อง API จากการถูกใช้ในทางที่ผิด token bucket และ sliding window เป็นอัลกอริทึมทั่วไป และมักจำกัดต่อผู้ใช้หรือคีย์ API
ไมโครเซอร์วิสแบ่งผลิตภัณฑ์เป็นบริการที่ deploy แยกกันได้โดยมีขอบเขตชัดเจน หลีกเลี่ยงการใช้ฐานข้อมูลเดียวร่วมกัน และใช้ API gatewayเพื่อรวมการยืนยันตัวตน การ routing และการจำกัด
คิวข้อความแยกผู้ผลิตและผู้บริโภค การส่งแบบ at-least-once อาจสร้างรายการซ้ำ ผู้บริโภคจึงควรเป็น idempotent และ dead-letter queue เก็บข้อความที่ล้มเหลวซ้ำ
ตัวอย่าง: บริการสั่งซื้อเขียน event ไปยังคิว บริการชำระเงินรับไปประมวลผล และบริการแจ้งเตือนฟังผลลัพธ์
เคล็ดลับฝึกฝน REST API ไมโครเซอร์วิส และคิวข้อความ: ทบทวนบทเรียนนี้ในเวลาสั้น ๆ ทุกวัน หลังทำแบบฝึกหัดแต่ละข้อให้บอกกฎหรือขั้นตอนที่ใช้ ถ้าบอกไม่ได้ ให้ทบทวนหัวข้อนั้นก่อนไปต่อ ความสม่ำเสมอช่วยจำได้ดีกว่าการอ่านนาน ๆ ครั้งเดียว
ตัวอย่าง
การออกแบบ API: GET /users/{id}/orders?cursor=... คืนหน้าคำสั่งซื้อพร้อม cursor ถัดไป จำกัดต่อผู้ใช้ด้วย token bucket 100 คำขอต่อนาที
การจัดการความล้มเหลว: หากการชำระเงินช้า ให้เผยแพร่ event คำสั่งซื้อไปยังคิว แล้วให้บริการชำระเงินรับไปประมวลผล ข้อความที่ล้มเหลวจะเข้าสู่ dead-letter queue
อ่านคำถามอีกครั้งก่อนจบ และตรวจสอบว่าคำตอบตรงกับสิ่งที่ถาม
บทเรียน 5 ความน่าเชื่อถือ การสังเกตการณ์ และความปลอดภัย
ระบบที่เชื่อถือได้จะล้มเหลวอย่างสง่างาม ใช้retry แบบ exponential backoff และ jitterสำหรับข้อผิดพลาดชั่วคราว และเพิ่มcircuit breakerเพื่อหยุดเรียกบริการที่ล้มเหลวก่อนทรัพยากรจะหมด
Bulkheadแยกกลุ่มทรัพยากรเพื่อไม่ให้บริการช้าหนึ่งใช้การเชื่อมต่อทั้งหมด กำหนด timeout และพฤติกรรม fallback สำหรับฟีเจอร์ที่ไม่สำคัญ
การสังเกตการณ์รวม metrics logs และ traces metrics แสดงสุขภาพ logs อธิบายเหตุการณ์ และ distributed traces ตามคำขอหนึ่งข้ามบริการ กำหนด SLI และ SLO เพื่อให้ทีมรู้ว่าเมื่อใดต้องดำเนินการ
ความปลอดภัยต้องเป็นส่วนหนึ่งของการออกแบบ: TLS สำหรับข้อมูลระหว่างทาง การยืนยันตัวตนที่ gateway การเข้าถึงสิทธิ์น้อยที่สุด การจัดการ secret และ rate limiting สำหรับ endpoint สาธารณะ
พูดถึงต้นทุนและความจุด้วย: เลือกขนาด instance ที่เหมาะสม ใช้ autoscaling ย้ายข้อมูลเย็นไปเก็บที่ถูกกว่า และหลีกเลี่ยงทรัพยากรที่ไม่ได้ใช้งาน
ใช้คลังคำถาม 50 ข้อที่เชื่อมโยงกันเป็นการสอบจำลอง: ตอบภายใต้เวลาจำกัด แยกหมวดข้อผิดพลาด และทำซ้ำหลัง 24 ชั่วโมง 3 วัน และ 7 วัน
เคล็ดลับฝึกฝน ความน่าเชื่อถือ การสังเกตการณ์ และความปลอดภัย: ทบทวนบทเรียนนี้ในเวลาสั้น ๆ ทุกวัน หลังทำแบบฝึกหัดแต่ละข้อให้บอกกฎหรือขั้นตอนที่ใช้ ถ้าบอกไม่ได้ ให้ทบทวนหัวข้อนั้นก่อนไปต่อ ความสม่ำเสมอช่วยจำได้ดีกว่าการอ่านนาน ๆ ครั้งเดียว
ตัวอย่าง
แผนความน่าเชื่อถือ: ลองชำระเงินที่ล้มเหลวสามครั้งด้วย exponential backoff และ jitter จากนั้นเปิด circuit breaker 30 วินาที ติดตามคำขอด้วย request_idร่วมกันและแจ้งเตือนเมื่อ p99 latency เกิน 500 ms
ความปลอดภัย: ใช้ TLS ยืนยันตัวตนผ่าน gateway เก็บ secret ใน vault และจำกัดอัตราการเรียก endpoint login
อ่านคำถามอีกครั้งก่อนจบ และตรวจสอบว่าคำตอบตรงกับสิ่งที่ถาม