- rqlite เป็นฐานข้อมูลเชิงสัมพันธ์แบบกระจายโอเพนซอร์สน้ำหนักเบา เขียนด้วย Go และพัฒนาขึ้นบนพื้นฐานของ SQLite และ Raft
- เริ่มพัฒนาตั้งแต่ปี 2014 โดยให้ความสำคัญกับความน่าเชื่อถือและคุณภาพเป็นอันดับแรก และแม้ผ่านการพัฒนาและใช้งานจริงมากว่า 10 ปี ก็มีรายงานกรณี panic ในสภาพแวดล้อมโปรดักชันน้อยกว่า 10 ครั้ง
- การทดสอบระบบแบบกระจายต้องอาศัยการพิจารณาอย่างรอบคอบในหลายชั้น และยึดแนวคิดการรักษาคุณภาพไว้ภายใต้ความเรียบง่าย
พีระมิดการทดสอบ: แนวทางที่มีประสิทธิภาพ
- การทดสอบของ rqlite ปฏิบัติตาม "พีระมิดการทดสอบ"
- พีระมิดการทดสอบ: โครงสร้างที่มีการทดสอบหน่วยเป็นฐาน และประกอบด้วยการทดสอบการทำงานร่วมกันรวมถึงการทดสอบ end-to-end (E2E) ในปริมาณน้อยที่สุด
- ช่วยให้ได้ชุดทดสอบที่มีประสิทธิภาพ ดีบักง่าย และมุ่งเป้าชัดเจน
การทดสอบหน่วย: หัวใจของคุณภาพ
- การทดสอบหน่วยใช้ทดสอบคอมโพเนนต์ที่แยกเป็นอิสระ และให้สมดุลระหว่างความเร็วกับความแม่นยำ
- ด้วย SQLite และสถาปัตยกรรมแบบ "shared nothing" ฟังก์ชันส่วนใหญ่จึงครอบคลุมได้ด้วยการทดสอบหน่วย
- จากโค้ด rqlite ทั้งหมด (ประมาณ 75,000 บรรทัด) การทดสอบหน่วยมีอยู่ราว 27,000 บรรทัด
- การทดสอบเสร็จสิ้นได้ภายในไม่กี่นาที ทำให้สามารถรันทดสอบได้บ่อยครั้งระหว่างการพัฒนา
การทดสอบระดับระบบ: ตรวจสอบ consensus
- การทดสอบระดับระบบใช้ตรวจสอบปฏิสัมพันธ์ระหว่างโมดูล consensus ของ Raft กับ SQLite
- รายการทดสอบหลัก:
- การจำลองคำสั่ง SQLite ระหว่างโหนด
- การอ่านข้อมูลภายใต้ระดับความสอดคล้องที่หลากหลาย
- การกู้คืนจากความล้มเหลวของคลัสเตอร์และการเลือก leader
- ด้วยโค้ดทดสอบประมาณ 7,000 บรรทัด จึงครอบคลุมปฏิสัมพันธ์ของทั้งการตั้งค่าแบบโหนดเดี่ยวและหลายโหนดอย่างรอบด้าน
การทดสอบ end-to-end: ชั้นที่มีให้น้อยที่สุด
- การทดสอบ end-to-end ทำหน้าที่เป็น smoke test เพื่อตรวจสอบการเริ่มระบบ การรวมคลัสเตอร์ และการทำงานพื้นฐานของระบบ
- เขียนด้วย Python และตรวจสอบฟังก์ชันหลักโดยรันคลัสเตอร์ rqlite จริง
- ตัวอย่าง: การตรวจสอบการสำรองข้อมูลไปยัง AWS S3
- จำกัดแนวทางไว้ที่โค้ดทดสอบประมาณ 5,000 บรรทัด เพื่อลดต้นทุนการดีบักให้น้อยที่สุด
การทดสอบประสิทธิภาพ: ทดสอบขีดจำกัด
- การทดสอบประสิทธิภาพประเมินเมตริกต่อไปนี้:
- ความเร็วสูงสุดของ INSERT
- การประมวลผลคิวรีพร้อมกัน
- การเปรียบเทียบการใช้หน่วยความจำ CPU และดิสก์
- รวมถึงการทดสอบฐานข้อมูล SQLite ขนาดมากกว่า 2GB เพื่อวิเคราะห์การจัดการหน่วยความจำและคอขวดของการเขียนลงดิสก์
- ช่วยค้นหาปัญหาด้านประสิทธิภาพและรับประกันเสถียรภาพผ่านการปรับแต่ง
บทเรียนที่ได้
- เริ่มทดสอบตั้งแต่เนิ่นๆ
- การทดสอบหน่วยเป็นวิธีที่มีประสิทธิภาพที่สุดในการสร้างความเชื่อมั่นต่อระบบ
- ไม่ควรเลื่อนการเขียนการทดสอบหน่วยระหว่างการพัฒนา เพราะสามารถพบบั๊กได้เร็วกว่าการทดสอบการทำงานร่วมกันหรือ E2E
- ทำให้โค้ดทดสอบเรียบง่าย
- ชุดทดสอบไม่ใช่สถานที่สำหรับยึดติดกับการรีแฟกเตอร์ที่ซับซ้อนหรือหลักการ DRY (Don't Repeat Yourself) มากเกินไป
- สิ่งสำคัญคือการเขียนโค้ดที่เข้าใจง่าย และควรยอมรับโค้ด boilerplate เพิ่มเติมได้
- ตรวจสอบการทดสอบด้วย
- ตอนเขียนการทดสอบ ให้สลับผลลัพธ์ที่คาดไว้เป็นตรงกันข้ามชั่วคราวแล้วรันใหม่
- หากการทดสอบเขียนได้ถูกต้อง กรณีนี้ควรล้มเหลว ซึ่งช่วยป้องกันข้อผิดพลาดในโค้ดทดสอบได้ล่วงหน้า
- อย่าเพิกเฉยต่อการทดสอบที่ล้มเหลว
- แม้จะเป็นความล้มเหลวที่เข้าใจยากหรือเกิดขึ้นไม่บ่อย ก็ยังให้ข้อมูลสำคัญเกี่ยวกับซอฟต์แวร์
- กรณีความล้มเหลวที่ดีบักยากมักเป็นโอกาสในการค้นพบข้อบกพร่องร้ายแรงในโค้ด
- เพิ่มความเป็น deterministic ให้มากที่สุด
- สร้างกลไกที่สามารถสั่งให้กระบวนการอัตโนมัติของระบบทำงานแบบแมนนวลได้
- ตัวอย่าง: ฟังก์ชัน snapshot ของ Raft ปกติทำงานแบบกึ่งอัตโนมัติ แต่ถูกออกแบบให้ trigger ได้อย่างชัดเจนระหว่างการทดสอบ
- ใช้แนวทางอย่างรอบคอบ (Be Deliberate)
- เพิ่มการทดสอบการทำงานร่วมกันระดับสูงหรือการทดสอบ E2E เฉพาะเมื่อมีการพิสูจน์ความจำเป็นอย่างชัดเจนแล้วเท่านั้น
- การทดสอบมากเกินไปอาจทำให้การพัฒนาและการดีบักช้าลง
- นำไปใช้และทำซ้ำ
- ในการทดสอบประสิทธิภาพพบว่า การเรียก fsync เป็นคอขวดหลัก จึงบีบอัดรายการล็อกของ Raft ก่อนเขียนลงดิสก์เพื่อเพิ่มประสิทธิภาพการใช้ดิสก์
- ให้ความสำคัญกับประสิทธิผล
- รักษาชุดทดสอบที่รันได้ภายในไม่กี่นาที เพื่อให้พัฒนาแบบวนรอบได้อย่างรวดเร็ว
- นี่คือข้อได้เปรียบสำคัญต่อการดูแลรักษาและทำให้โปรเจกต์โอเพนซอร์สยังคงมีความเคลื่อนไหว
คุณภาพมาก่อน
- ปฏิบัติตามพีระมิดการทดสอบ และออกแบบให้แต่ละชั้นของการทดสอบมีจุดประสงค์ชัดเจน
- เมื่อความซับซ้อนของระบบแบบกระจายเพิ่มขึ้น การรักษาความเรียบง่ายของการทดสอบคือหัวใจสำคัญ
- เป้าหมายคือการสร้างฐานข้อมูลที่เชื่อถือได้และใช้งานดูแลได้ง่าย
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
เทสต์แรกยากที่สุด แต่ก็คุ้มค่าที่จะเพิ่ม หลังจากนั้นเทสต์ถัดไปจะง่ายขึ้น
ความทุ่มเทต่อโปรเจ็กต์นี้น่าประทับใจ
เข้าใจแนวคิด test pyramid แต่บ่อยครั้งก็มักไม่มีครบทุกระดับ จึงเป็นสถานการณ์ที่ต้องรีบปรับปรุง
ดูเหมือนจะมีข้อผิดพลาดจากการคัดลอกแล้ววางใน FAQ
กำลังรอรายงาน Jepsen อยู่
ชอบในรูปแบบวิดีโอด้วย
อิจฉาการตั้งค่าการทดสอบประสิทธิภาพ
เคยใช้ rqlite และมันถ่ายทอดความเรียบง่ายออกมาได้ดี
กำลังถามความเห็นเกี่ยวกับการทดสอบแบบ deterministic simulation
สงสัยว่ามีการใช้ rqlite ในสภาพแวดล้อมจริงหรือไม่
rqlite เป็นโปรเจ็กต์ที่แปลกใหม่และอัจฉริยะ