สำรวจอัลกอริทึมฉันทามติแบบกระจาย Raft หลักการปฏิบัติงาน ข้อควรพิจารณาในการนำไปใช้จริง และการใช้งานจริงเพื่อสร้างระบบที่ยืดหยุ่นและปรับขนาดได้ทั่วโลก
การบรรลุฉันทามติแบบกระจาย: เจาะลึกการนำอัลกอริทึม Raft ไปใช้สำหรับระบบทั่วโลก
ในโลกที่เชื่อมโยงถึงกันมากขึ้น ระบบแบบกระจายคือกระดูกสันหลังของบริการดิจิทัลเกือบทั้งหมด ตั้งแต่แพลตฟอร์มอีคอมเมิร์ซ สถาบันการเงิน ไปจนถึงโครงสร้างพื้นฐานคลาวด์คอมพิวติ้ง และเครื่องมือสื่อสารแบบเรียลไทม์ ระบบเหล่านี้มอบความสามารถในการปรับขนาด ความพร้อมใช้งาน และความยืดหยุ่นที่ไม่มีใครเทียบได้ โดยการกระจายภาระงานและข้อมูลไปยังเครื่องหลายเครื่อง อย่างไรก็ตาม พลังนี้มาพร้อมกับความท้าทายที่สำคัญ: การทำให้แน่ใจว่าส่วนประกอบทั้งหมดเห็นพ้องกันเกี่ยวกับสถานะของระบบ แม้จะมีความล่าช้าของเครือข่าย ข้อผิดพลาดของโหนด และการดำเนินการพร้อมกัน ปัญหานี้เป็นที่รู้จักในชื่อ การบรรลุฉันทามติแบบกระจาย
การบรรลุฉันทามติในสภาพแวดล้อมแบบกระจายที่ไม่มีการซิงโครไนซ์และมีแนวโน้มที่จะเกิดข้อผิดพลาดนั้นซับซ้อนอย่างมาก เป็นเวลาหลายทศวรรษที่ Paxos เป็นอัลกอริทึมหลักในการแก้ปัญหานี้ ซึ่งได้รับการยกย่องในด้านความถูกต้องทางทฤษฎี แต่ก็มักถูกวิพากษ์วิจารณ์ในเรื่องความซับซ้อนและความยากในการนำไปใช้ จากนั้น Raft ก็ถือกำเนิดขึ้น เป็นอัลกอริทึมที่ออกแบบมาโดยมีเป้าหมายหลักคือ ความสามารถในการทำความเข้าใจ Raft มุ่งมั่นที่จะมีความเท่าเทียมกับ Paxos ในแง่ของความทนทานต่อข้อผิดพลาดและประสิทธิภาพ แต่มีโครงสร้างที่ง่ายกว่ามากสำหรับนักพัฒนาในการทำความเข้าใจและต่อยอด
คู่มือที่ครอบคลุมนี้จะเจาะลึกอัลกอริทึม Raft โดยสำรวจหลักการพื้นฐาน กลไกการทำงาน ข้อควรพิจารณาในการนำไปใช้จริง และบทบาทสำคัญในการสร้างแอปพลิเคชันแบบกระจายทั่วโลกที่มีความแข็งแกร่ง ไม่ว่าคุณจะเป็นสถาปนิกผู้มีประสบการณ์ วิศวกรระบบแบบกระจาย หรือนักพัฒนาที่ต้องการสร้างบริการที่มีความพร้อมใช้งานสูง การทำความเข้าใจ Raft เป็นก้าวที่จำเป็นสู่การเป็นผู้เชี่ยวชาญด้านความซับซ้อนของการประมวลผลสมัยใหม่
ความจำเป็นที่ไม่สามารถละเลยได้ของการบรรลุฉันทามติแบบกระจายในสถาปัตยกรรมสมัยใหม่
ลองนึกภาพแพลตฟอร์มอีคอมเมิร์ซทั่วโลกที่ประมวลผลธุรกรรมหลายล้านรายการต่อวินาที ข้อมูลลูกค้า ระดับสินค้าคงคลัง สถานะคำสั่งซื้อ ทั้งหมดต้องมีความสอดคล้องกันทั่วศูนย์ข้อมูลหลายแห่งที่กระจายอยู่ทั่วทวีป บัญชีแยกประเภทของระบบธนาคารที่กระจายอยู่บนเซิร์ฟเวอร์หลายเครื่อง ไม่สามารถยอมให้มีความแตกต่างแม้แต่วินาทีเดียวเกี่ยวกับยอดคงเหลือในบัญชี สถานการณ์เหล่านี้เน้นย้ำถึงความสำคัญของการบรรลุฉันทามติแบบกระจาย
ความท้าทายโดยธรรมชาติของระบบแบบกระจาย
ระบบแบบกระจาย โดยธรรมชาติแล้ว ก่อให้เกิดความท้าทายมากมายที่ไม่มีอยู่ในแอปพลิเคชันแบบโมโนลิธ การทำความเข้าใจความท้าทายเหล่านี้เป็นสิ่งสำคัญในการชื่นชมความสง่างามและความจำเป็นของอัลกอริทึมเช่น Raft:
- ความล้มเหลวบางส่วน: แตกต่างจากเซิร์ฟเวอร์เดียวที่ทำงานหรือล้มเหลวโดยสมบูรณ์ ระบบแบบกระจายอาจมีโหนดบางโหนดล้มเหลวในขณะที่โหนดอื่นยังคงทำงานอยู่ เซิร์ฟเวอร์อาจขัดข้อง การเชื่อมต่อเครือข่ายอาจหลุด หรือดิสก์อาจเสียหาย ทั้งหมดนี้ในขณะที่ส่วนที่เหลือของคลัสเตอร์ยังคงทำงาน ระบบต้องดำเนินการต่อไปอย่างถูกต้องแม้จะมีความล้มเหลวบางส่วนเหล่านี้
- พาร์ติชั่นเครือข่าย: เครือข่ายที่เชื่อมต่อโหนดต่างๆ ไม่ได้มีความน่าเชื่อถือเสมอไป พาร์ติชั่นเครือข่ายเกิดขึ้นเมื่อการสื่อสารระหว่างกลุ่มโหนดถูกตัดขาด ทำให้ดูเหมือนว่าโหนดบางโหนดล้มเหลว แม้ว่าโหนดเหล่านั้นจะยังคงทำงานอยู่ การแก้ไขสถานการณ์ "split-brain" เหล่านี้ ซึ่งส่วนต่างๆ ของระบบทำงานอย่างอิสระโดยอาศัยข้อมูลที่ล้าสมัยหรือไม่สอดคล้องกัน เป็นปัญหาฉันทามติหลัก
- การสื่อสารแบบอะซิงโครนัส: ข้อความระหว่างโหนดอาจล่าช้า ถูกจัดลำดับใหม่ หรือสูญหายทั้งหมด ไม่มีนาฬิกาทั่วโลกหรือการรับประกันเกี่ยวกับเวลาในการส่งข้อความ ทำให้ยากต่อการกำหนดลำดับเหตุการณ์ที่สอดคล้องกันหรือสถานะระบบที่แน่นอน
- การทำงานพร้อมกัน: โหนดหลายโหนดอาจพยายามอัปเดตข้อมูลเดียวกันหรือเริ่มการดำเนินการพร้อมกัน หากไม่มีกลไกในการประสานงานการดำเนินการเหล่านี้ ความขัดแย้งและความไม่สอดคล้องกันนั้นหลีกเลี่ยงไม่ได้
- ความหน่วงแฝงที่คาดเดาไม่ได้: โดยเฉพาะอย่างยิ่งในการใช้งานแบบกระจายทั่วโลก ความหน่วงแฝงของเครือข่ายอาจแตกต่างกันอย่างมาก การดำเนินการที่รวดเร็วในภูมิภาคหนึ่งอาจช้าในอีกภูมิภาคหนึ่ง ส่งผลต่อกระบวนการตัดสินใจและการประสานงาน
ทำไมฉันทามติจึงเป็นรากฐานของความน่าเชื่อถือ
อัลกอริทึมฉันทามติเป็นส่วนประกอบพื้นฐานในการแก้ปัญหาเหล่านี้ พวกเขาสามารถทำให้ชุดส่วนประกอบที่ไม่น่าเชื่อถือทำงานร่วมกันเป็นหน่วยเดียวที่น่าเชื่อถือและสอดคล้องกันอย่างสูง โดยเฉพาะอย่างยิ่ง ฉันทามติช่วยให้บรรลุ:
- การจำลองสถานะเครื่อง (SMR): แนวคิดหลักเบื้องหลังระบบแบบกระจายที่ทนทานต่อข้อผิดพลาดจำนวนมาก หากโหนดทั้งหมดเห็นพ้องกันเกี่ยวกับลำดับการดำเนินการ และหากแต่ละโหนดเริ่มต้นในสถานะเริ่มต้นเดียวกันและดำเนินการตามคำสั่งเหล่านั้นตามลำดับเดียวกัน โหนดทั้งหมดจะมาถึงสถานะสุดท้ายเดียวกัน ฉันทามติคือกลไกในการตกลงเกี่ยวกับลำดับการดำเนินการทั่วโลกนี้
- ความพร้อมใช้งานสูง: โดยการอนุญาตให้ระบบทำงานต่อไปได้แม้ว่าโหนดส่วนน้อยจะล้มเหลว ฉันทามติจะทำให้มั่นใจได้ว่าบริการยังคงสามารถเข้าถึงได้และทำงานได้ โดยลดการหยุดทำงานให้น้อยที่สุด
- ความสอดคล้องของข้อมูล: รับประกันว่าสำเนาข้อมูลทั้งหมดจะยังคงซิงโครไนซ์ ป้องกันการอัปเดตที่ขัดแย้งกัน และรับประกันว่าลูกค้าจะอ่านข้อมูลที่ทันสมัยและถูกต้องที่สุดเสมอ
- ความทนทานต่อข้อผิดพลาด: ระบบสามารถทนทานต่อความล้มเหลวของโหนดตามอำเภอใจจำนวนหนึ่ง (ปกติคือความล้มเหลวแบบคราส) และยังคงดำเนินการต่อไปได้โดยไม่ต้องมีการแทรกแซงจากมนุษย์
แนะนำ Raft: แนวทางที่เข้าใจได้สู่ฉันทามติ
Raft ถือกำเนิดจากโลกวิชาการโดยมีเป้าหมายที่ชัดเจน: ทำให้การบรรลุฉันทามติแบบกระจายเข้าถึงได้ ผู้เขียน Diego Ongaro และ John Ousterhout ได้ออกแบบ Raft โดยเน้นความสามารถในการทำความเข้าใจเป็นพิเศษ โดยมีเป้าหมายเพื่อให้สามารถนำอัลกอริทึมฉันทามติไปใช้อย่างแพร่หลายและถูกต้อง
ปรัชญาการออกแบบหลักของ Raft: เน้นความเข้าใจเป็นอันดับแรก
Raft แบ่งปัญหาที่ซับซ้อนของการบรรลุฉันทามติออกเป็นปัญหาย่อยๆ ที่ค่อนข้างเป็นอิสระหลายอย่าง โดยแต่ละอย่างมีชุดกฎและพฤติกรรมเฉพาะของตนเอง โมดูลาร์นี้ช่วยให้เข้าใจได้มาก หลักการออกแบบที่สำคัญ ได้แก่:
- แนวทางที่เน้นผู้นำเป็นหลัก: แตกต่างจากอัลกอริทึมฉันทามติอื่น ๆ ที่โหนดทั้งหมดมีส่วนร่วมในการตัดสินใจเท่าเทียมกัน Raft กำหนดผู้นำเพียงคนเดียว ผู้นำมีหน้าที่รับผิดชอบในการจัดการบันทึกที่จำลองและประสานคำขอของไคลเอ็นต์ทั้งหมด สิ่งนี้ช่วยลดความซับซ้อนของการจัดการบันทึกและลดความซับซ้อนของการโต้ตอบระหว่างโหนด
- ผู้นำที่แข็งแกร่ง: ผู้นำคือหน่วยงานสูงสุดในการเสนอรายการบันทึกใหม่และกำหนดว่ารายการเหล่านั้นจะถูกคอมมิตเมื่อใด ผู้ติดตามจะจำลองบันทึกของผู้นำแบบพาสซีฟและตอบสนองต่อคำขอของผู้นำ
- การเลือกตั้งแบบกำหนดได้: Raft ใช้การหมดเวลาการเลือกตั้งแบบสุ่มเพื่อให้แน่ใจว่าโดยทั่วไปมีผู้สมัครเพียงคนเดียวที่จะปรากฏตัวเป็นผู้นำในการเลือกตั้งแต่ละครั้ง
- ความสอดคล้องของบันทึก: Raft บังคับใช้คุณสมบัติความสอดคล้องที่แข็งแกร่งในบันทึกที่จำลองไว้ เพื่อให้แน่ใจว่ารายการที่คอมมิตจะไม่ถูกย้อนกลับ และรายการที่คอมมิตทั้งหมดจะปรากฏบนโหนดที่พร้อมใช้งานทั้งหมดในที่สุด
การเปรียบเทียบสั้นๆ กับ Paxos
ก่อน Raft Paxos เป็นมาตรฐานโดยพฤตินัยสำหรับการบรรลุฉันทามติแบบกระจาย แม้ว่าจะมีประสิทธิภาพ Paxos ก็เป็นที่รู้จักกันดีว่าเข้าใจและนำไปใช้ได้อย่างถูกต้อง การออกแบบซึ่งแยกบทบาท (ผู้เสนอ ผู้ยอมรับ ผู้เรียน) และอนุญาตให้มีผู้นำหลายคนพร้อมกัน (แม้ว่าจะมีเพียงคนเดียวที่สามารถคอมมิตค่าได้) อาจนำไปสู่การโต้ตอบที่ซับซ้อนและกรณีพิเศษ
ในทางตรงกันข้าม Raft ช่วยลดพื้นที่สถานะให้เรียบง่าย มันบังคับใช้แบบจำลองผู้นำที่แข็งแกร่ง โดยผู้นำมีหน้าที่รับผิดชอบการเปลี่ยนแปลงบันทึกทั้งหมด มันกำหนดบทบาท (ผู้นำ ผู้ติดตาม ผู้สมัคร) และการเปลี่ยนระหว่างบทบาทเหล่านี้อย่างชัดเจน โครงสร้างนี้ทำให้พฤติกรรมของ Raft เข้าใจง่ายขึ้นและง่ายต่อการให้เหตุผล นำไปสู่ข้อผิดพลาดในการนำไปใช้น้อยลงและวงจรการพัฒนาที่เร็วขึ้น ระบบในโลกแห่งความเป็นจริงหลายแห่งที่ประสบปัญหาเกี่ยวกับ Paxos ในตอนแรกพบว่าประสบความสำเร็จโดยการนำ Raft มาใช้
บทบาทพื้นฐานสามบทบาทใน Raft
ณ เวลาใดก็ตาม เซิร์ฟเวอร์แต่ละเครื่องในคลัสเตอร์ Raft จะอยู่ในสถานะใดสถานะหนึ่งในสามสถานะ: ผู้นำ, ผู้ติดตาม, หรือ ผู้สมัคร บทบาทเหล่านี้มีความเป็นเอกสิทธิ์และเปลี่ยนแปลงได้ โดยเซิร์ฟเวอร์เปลี่ยนระหว่างบทบาทตามกฎและเหตุการณ์เฉพาะ
1. ผู้ติดตาม
- บทบาทแบบพาสซีฟ: ผู้ติดตามเป็นสถานะที่พาสซีฟที่สุดใน Raft พวกเขาเพียงแค่ตอบสนองต่อคำขอจากผู้นำและผู้สมัคร
-
รับ Heartbeats: ผู้ติดตามคาดว่าจะได้รับ Heartbeats (AppendEntries RPCs ที่ว่างเปล่า) จากผู้นำเป็นระยะ หากผู้ติดตามไม่ได้รับ Heartbeat หรือ AppendEntries RPC ภายในระยะเวลา
election timeoutที่กำหนด พวกเขาจะสันนิษฐานว่าผู้นำล้มเหลวและเปลี่ยนไปสู่สถานะผู้สมัคร - การลงคะแนน: ในระหว่างการเลือกตั้ง ผู้ติดตามจะลงคะแนนให้ผู้สมัครอย่างน้อยหนึ่งรายต่อเทอม
- การจำลองบันทึก: ผู้ติดตามจะผนวกรายการบันทึกไปยังบันทึกภายในของตนตามที่ผู้นำสั่ง
2. ผู้สมัคร
- การเริ่มการเลือกตั้ง: เมื่อผู้ติดตามหมดเวลา (ไม่ได้รับการติดต่อจากผู้นำ) พวกเขาจะเปลี่ยนไปสู่สถานะผู้สมัครเพื่อเริ่มการเลือกตั้งใหม่
-
การลงคะแนนให้ตนเอง: ผู้สมัครจะเพิ่ม
current termของตนเอง ลงคะแนนให้ตนเอง และส่งRequestVoteRPCs ไปยังเซิร์ฟเวอร์อื่นทั้งหมดในคลัสเตอร์ - การชนะการเลือกตั้ง: หากผู้สมัครได้รับการลงคะแนนจากเซิร์ฟเวอร์ส่วนใหญ่ในคลัสเตอร์สำหรับเทอมเดียวกัน พวกเขาจะเปลี่ยนไปสู่สถานะผู้นำ
- การลงจากตำแหน่ง: หากผู้สมัครค้นพบเซิร์ฟเวอร์อื่นที่มีเทอมสูงกว่า หรือหากพวกเขาได้รับ AppendEntries RPC จากผู้นำที่ถูกต้อง พวกเขาจะกลับไปสู่สถานะผู้ติดตาม
3. ผู้นำ
- อำนาจสูงสุด: มีผู้นำเพียงคนเดียวในคลัสเตอร์ Raft ณ เวลาใดเวลาหนึ่ง (สำหรับเทอมที่กำหนด) ผู้นำมีหน้าที่รับผิดชอบการโต้ตอบกับไคลเอ็นต์ทั้งหมด การจำลองบันทึก และการรับประกันความสอดคล้อง
-
การส่ง Heartbeats: ผู้นำจะส่ง
AppendEntriesRPCs (Heartbeats) ไปยังผู้ติดตามทั้งหมดเป็นระยะๆ เพื่อรักษาอำนาจของตนและป้องกันการเลือกตั้งใหม่ - การจัดการบันทึก: ผู้นำยอมรับคำขอของไคลเอ็นต์ ผนวกรายการบันทึกใหม่เข้ากับบันทึกภายในของตน แล้วจำลองรายการเหล่านั้นไปยังผู้ติดตามทั้งหมด
- การคอมมิต: ผู้นำตัดสินใจว่ารายการใดถูกจำลองอย่างปลอดภัยไปยังเซิร์ฟเวอร์ส่วนใหญ่และสามารถคอมมิตไปยังเครื่องสถานะได้
-
การลงจากตำแหน่ง: หากผู้นำค้นพบเซิร์ฟเวอร์ที่มี
termสูงกว่า พวกเขาจะลงจากตำแหน่งทันทีและกลับไปเป็นผู้ติดตาม นี่เป็นการรับประกันว่าระบบจะดำเนินต่อไปด้วยเทอมที่สูงที่สุดที่รู้จักเสมอ
ระยะการทำงานของ Raft: การสำรวจโดยละเอียด
Raft ทำงานผ่านวงจรการเลือกตั้งผู้นำและการจำลองบันทึกอย่างต่อเนื่อง กลไกหลักสองประการนี้ ควบคู่ไปกับคุณสมบัติด้านความปลอดภัยที่สำคัญ จะทำให้มั่นใจได้ว่าคลัสเตอร์จะรักษาความสอดคล้องและความทนทานต่อข้อผิดพลาด
1. การเลือกตั้งผู้นำ
กระบวนการเลือกตั้งผู้นำเป็นพื้นฐานของการทำงานของ Raft เพื่อให้แน่ใจว่าคลัสเตอร์จะมีโหนดที่มีอำนาจในการประสานงานการดำเนินการเพียงโหนดเดียวเสมอ
-
Election Timeout: ผู้ติดตามแต่ละคนจะรักษา
election timeoutแบบสุ่ม (โดยทั่วไปคือ 150-300ms) หากผู้ติดตามไม่ได้รับข้อมูลการสื่อสารใดๆ (Heartbeat หรือ AppendEntries RPC) จากผู้นำปัจจุบันภายในระยะเวลาหมดเวลานี้ พวกเขาจะสันนิษฐานว่าผู้นำล้มเหลวหรือเกิดพาร์ติชั่นเครือข่าย -
การเปลี่ยนไปเป็นผู้สมัคร: เมื่อหมดเวลา ผู้ติดตามจะเปลี่ยนไปสู่สถานะ
Candidateพวกเขาจะเพิ่มcurrent termของตนเอง ลงคะแนนให้ตนเอง และรีเซ็ตตัวจับเวลาการเลือกตั้ง -
RequestVote RPC: จากนั้นผู้สมัครจะส่ง
RequestVoteRPCs ไปยังเซิร์ฟเวอร์อื่นทั้งหมดในคลัสเตอร์ RPC นี้ประกอบด้วยcurrent termของผู้สมัครcandidateIdและข้อมูลเกี่ยวกับlast log indexและlast log termของตน (จะกล่าวถึงเหตุผลที่สำคัญต่อความปลอดภัยในภายหลัง) -
กฎการลงคะแนน: เซิร์ฟเวอร์จะให้สิทธิ์ลงคะแนนแก่ผู้สมัคร หาก:
-
current termของเซิร์ฟเวอร์น้อยกว่าหรือเท่ากับเทอมของผู้สมัคร - เซิร์ฟเวอร์ยังไม่ได้ลงคะแนนให้ผู้สมัครรายอื่นในเทอมปัจจุบัน
-
บันทึกของผู้สมัครมีความทันสมัยอย่างน้อยเท่ากับบันทึกของเซิร์ฟเวอร์เอง สิ่งนี้ถูกกำหนดโดยการเปรียบเทียบ
last log termก่อน จากนั้นlast log indexหากเทอมเท่ากัน ผู้สมัคร "ทันสมัย" คือหากบันทึกของเขามีรายการที่คอมมิตทั้งหมดที่บันทึกของผู้ลงคะแนนมีอยู่ สิ่งนี้เรียกว่า election restriction และมีความสำคัญต่อความปลอดภัย
-
-
การชนะการเลือกตั้ง: ผู้สมัครจะกลายเป็นผู้นำคนใหม่ หากได้รับการลงคะแนนจากเซิร์ฟเวอร์ส่วนใหญ่ในคลัสเตอร์สำหรับเทอมเดียวกัน เมื่อได้รับเลือก ผู้นำคนใหม่จะส่ง
AppendEntriesRPCs (Heartbeats) ไปยังเซิร์ฟเวอร์อื่นทั้งหมดทันทีเพื่อสร้างอำนาจของตนและป้องกันการเลือกตั้งใหม่ -
การลงคะแนนที่แบ่งแยกและการลองใหม่: เป็นไปได้ที่ผู้สมัครหลายคนจะเกิดขึ้นพร้อมกัน นำไปสู่การแบ่งคะแนนที่ไม่มีผู้สมัครคนใดได้รับคะแนนเสียงข้างมาก ในการแก้ไขปัญหานี้ ผู้สมัครแต่ละคนมี
election timeoutแบบสุ่ม หากelection timeoutของผู้สมัครหมดลงโดยไม่ชนะการเลือกตั้งหรือได้ยินจากผู้นำคนใหม่ พวกเขาจะเพิ่มเทอมของตนและเริ่มการเลือกตั้งใหม่ การสุ่มช่วยให้แน่ใจว่าการแบ่งคะแนนเกิดขึ้นได้ยากและได้รับการแก้ไขอย่างรวดเร็ว -
การค้นพบเทอมที่สูงกว่า: หากผู้สมัคร (หรือเซิร์ฟเวอร์ใดๆ) ได้รับ RPC ที่มี
termสูงกว่าcurrent termของตนเอง เซิร์ฟเวอร์นั้นจะอัปเดตcurrent termของตนให้เป็นค่าที่สูงขึ้นและกลับไปสู่สถานะfollowerทันที สิ่งนี้ทำให้มั่นใจได้ว่าเซิร์ฟเวอร์ที่มีข้อมูลที่ล้าสมัยจะไม่พยายามเป็นผู้นำหรือรบกวนผู้นำที่ถูกต้อง
2. การจำลองบันทึก
เมื่อผู้นำได้รับเลือกแล้ว หน้าที่หลักของพวกเขาคือการจัดการบันทึกที่จำลองไว้และรับประกันความสอดคล้องทั่วทั้งคลัสเตอร์ ซึ่งเกี่ยวข้องกับการยอมรับคำสั่งของไคลเอ็นต์ การผนวกเข้ากับบันทึกของพวกเขา และการจำลองไปยังผู้ติดตาม
- คำขอของไคลเอ็นต์: คำขอของไคลเอ็นต์ทั้งหมด (คำสั่งที่จะดำเนินการโดยเครื่องสถานะ) จะถูกส่งไปยังผู้นำ หากไคลเอ็นต์ติดต่อผู้ติดตาม ผู้ติดตามจะเปลี่ยนเส้นทางคำขอไปยังผู้นำปัจจุบัน
-
การผนวกเข้ากับบันทึกของผู้นำ: เมื่อผู้นำได้รับคำสั่งของไคลเอ็นต์ พวกเขาจะผนวกคำสั่งนั้นเป็น
log entryใหม่เข้ากับบันทึกภายในของตน แต่ละlog entryประกอบด้วยคำสั่งเองtermที่ได้รับ และlog index -
AppendEntries RPC: จากนั้นผู้นำจะส่ง
AppendEntriesRPCs ไปยังผู้ติดตามทั้งหมด โดยขอให้พวกเขามีรายการบันทึกใหม่ (หรือชุดของรายการ) เข้าไปในบันทึกของพวกเขา RPCs เหล่านี้ประกอบด้วย:-
term: เทอมปัจจุบันของผู้นำ -
leaderId: ID ของผู้นำ (สำหรับผู้ติดตามเพื่อเปลี่ยนเส้นทางไคลเอ็นต์) -
prevLogIndex: ดัชนีของรายการบันทึกที่อยู่ก่อนรายการใหม่โดยตรง -
prevLogTerm: เทอมของรายการprevLogIndexสองค่านี้ (prevLogIndex,prevLogTerm) มีความสำคัญอย่างยิ่งต่อคุณสมบัติการจับคู่บันทึก -
entries[]: รายการบันทึกที่จะจัดเก็บ (ว่างเปล่าสำหรับ Heartbeats) -
leaderCommit:commitIndexของผู้นำ (ดัชนีของรายการบันทึกที่ทราบว่าคอมมิตสูงสุด)
-
-
การตรวจสอบความสอดคล้อง (คุณสมบัติการจับคู่บันทึก): เมื่อผู้ติดตามได้รับ
AppendEntriesRPC พวกเขาจะทำการตรวจสอบความสอดคล้อง พวกเขาตรวจสอบว่าบันทึกของพวกเขามีรายการที่prevLogIndexที่มีเทอมตรงกับprevLogTermหรือไม่ หากการตรวจสอบนี้ล้มเหลว ผู้ติดตามจะปฏิเสธAppendEntriesRPC และแจ้งให้ผู้นำทราบว่าบันทึกของพวกเขาสอดคล้องกัน -
การแก้ไขความไม่สอดคล้องกัน: หากผู้ติดตามปฏิเสธ
AppendEntriesRPC ผู้นำจะลดค่าnextIndexสำหรับผู้ติดตามนั้นและลองAppendEntriesRPC อีกครั้งnextIndexคือดัชนีของรายการบันทึกถัดไปที่ผู้นำจะส่งไปยังผู้ติดตามแต่ละราย กระบวนการนี้จะดำเนินต่อไปจนกว่าnextIndexจะถึงจุดที่บันทึกของผู้นำและผู้ติดตามตรงกัน เมื่อพบการจับคู่แล้ว ผู้ติดตามสามารถยอมรับรายการบันทึกที่ตามมาได้ และในที่สุดจะนำบันทึกของพวกเขาสอดคล้องกับบันทึกของผู้นำ -
การคอมมิตรายการ: รายการจะถือว่า คอมมิต เมื่อผู้นำจำลองสำเร็จไปยังเซิร์ฟเวอร์ส่วนใหญ่ (รวมถึงตัวมันเอง) เมื่อคอมมิตแล้ว รายการนั้นสามารถนำไปใช้กับเครื่องสถานะได้ ผู้นำจะอัปเดต
commitIndexของตน และรวมสิ่งนี้ไว้ในAppendEntriesRPCs ถัดไปเพื่อแจ้งให้ผู้ติดตามทราบเกี่ยวกับรายการที่คอมมิต ผู้ติดตามจะอัปเดตcommitIndexของตนตามleaderCommitของผู้นำ และใช้รายการจนถึงดัชนีนั้นกับเครื่องสถานะของพวกเขา -
คุณสมบัติความสมบูรณ์ของผู้นำ: Raft รับประกันว่าหากรายการบันทึกถูกคอมมิตในเทอมที่กำหนด ผู้นำที่ตามมาทั้งหมดจะต้องมีรายการบันทึกนั้นด้วย คุณสมบัตินี้บังคับใช้โดย
election restriction: ผู้สมัครสามารถชนะการเลือกตั้งได้ก็ต่อเมื่อบันทึกของพวกเขามีความทันสมัยอย่างน้อยเท่ากับเซิร์ฟเวอร์ส่วนใหญ่ สิ่งนี้ป้องกันไม่ให้ผู้นำที่อาจเขียนทับหรือพลาดรายการที่คอมมิตได้รับการเลือกตั้ง
3. คุณสมบัติด้านความปลอดภัยและการรับประกัน
ความแข็งแกร่งของ Raft มาจากคุณสมบัติด้านความปลอดภัยหลายประการที่ออกแบบมาอย่างพิถีพิถันเพื่อป้องกันความไม่สอดคล้องกันและรับประกันความสมบูรณ์ของข้อมูล:
- Election Safety: จะมีผู้นำเพียงรายเดียวที่สามารถได้รับเลือกในเทอมที่กำหนดได้ สิ่งนี้บังคับใช้โดยกลไกการลงคะแนนที่ผู้ติดตามจะให้สิทธิ์ลงคะแนนอย่างน้อยหนึ่งครั้งต่อเทอม และผู้สมัครต้องการคะแนนเสียงข้างมาก
-
Leader Completeness: หากรายการบันทึกถูกคอมมิตในเทอมที่กำหนด รายการนั้นจะปรากฏในบันทึกของผู้นำทั้งหมดที่ตามมา สิ่งนี้มีความสำคัญอย่างยิ่งต่อการป้องกันการสูญเสียข้อมูลที่คอมมิต และส่วนใหญ่รับประกันโดย
election restriction - Log Matching Property: หากบันทึกสองรายการมีรายการที่มีดัชนีและเทอมเดียวกัน บันทึกเหล่านั้นจะเหมือนกันทุกประการในรายการก่อนหน้าทั้งหมด สิ่งนี้ช่วยลดความซับซ้อนของการตรวจสอบความสอดคล้องของบันทึก และช่วยให้ผู้นำนำบันทึกของผู้ติดตามให้ทันสมัยได้อย่างมีประสิทธิภาพ
-
Commit Safety: เมื่อรายการถูกคอมมิตแล้ว จะไม่มีการย้อนกลับหรือเขียนทับ สิ่งนี้เป็นผลโดยตรงจากคุณสมบัติ
Leader CompletenessและLog Matchingเมื่อรายการถูกคอมมิตแล้ว จะถือว่าถูกจัดเก็บถาวร
แนวคิดและกลไกหลักใน Raft
นอกเหนือจากบทบาทและระยะการทำงานแล้ว Raft ยังอาศัยแนวคิดหลักหลายประการในการจัดการสถานะและรับประกันความถูกต้อง
1. เทอม
term ใน Raft เป็นจำนวนเต็มที่เพิ่มขึ้นอย่างต่อเนื่อง ทำหน้าที่เป็นนาฬิกาเชิงตรรกะสำหรับคลัสเตอร์ แต่ละเทอมจะเริ่มต้นด้วยการเลือกตั้ง และหากการเลือกตั้งสำเร็จ ผู้นำเพียงคนเดียวจะได้รับเลือกสำหรับเทอมนั้น เทอมมีความสำคัญต่อการระบุข้อมูลที่ล้าสมัยและรับประกันว่าเซิร์ฟเวอร์จะพิจารณาข้อมูลที่ทันสมัยที่สุดเสมอ:
-
เซิร์ฟเวอร์จะแลกเปลี่ยน
current termของตนใน RPCs ทั้งหมด -
หากเซิร์ฟเวอร์ค้นพบเซิร์ฟเวอร์อื่นที่มี
termสูงกว่า เซิร์ฟเวอร์นั้นจะอัปเดตcurrent termของตนเองและกลับไปสู่สถานะfollower -
หากผู้สมัครหรือผู้นำค้นพบว่า
termของตนล้าสมัย (ต่ำกว่าtermของเซิร์ฟเวอร์อื่น) พวกเขาจะลงจากตำแหน่งทันที
2. รายการบันทึก
log เป็นส่วนประกอบหลักของ Raft เป็นลำดับของรายการที่สั่งซื้อ โดยแต่ละ log entry แทนคำสั่งที่จะดำเนินการโดยเครื่องสถานะ แต่ละรายการประกอบด้วย:
- Command: การดำเนินการจริงที่จะดำเนินการ (เช่น "ตั้งค่า x=5", "สร้างผู้ใช้")
- Term: เทอมที่สร้างรายการบนผู้นำ
- Index: ตำแหน่งของรายการในบันทึก รายการบันทึกจะถูกจัดลำดับตามดัชนีอย่างเคร่งครัด
บันทึกจะถูกคงอยู่ หมายความว่ารายการจะถูกเขียนไปยังที่จัดเก็บที่เสถียรก่อนที่จะตอบสนองต่อไคลเอ็นต์ ป้องกันการสูญเสียข้อมูลระหว่างการขัดข้อง
3. เครื่องสถานะ
เซิร์ฟเวอร์ทุกเครื่องในคลัสเตอร์ Raft จะรักษา state machine นี่เป็นส่วนประกอบที่เฉพาะเจาะจงของแอปพลิเคชันที่ประมวลผลรายการบันทึกที่คอมมิต เพื่อให้แน่ใจว่าสอดคล้องกัน เครื่องสถานะจะต้อง กำหนดได้ (เมื่อได้รับสถานะเริ่มต้นและลำดับคำสั่งเดียวกัน จะสร้างผลลัพธ์และสถานะสุดท้ายเหมือนเดิมเสมอ) และ ไม่ขึ้นกับลำดับ (การใช้คำสั่งเดียวกันหลายครั้งจะมีผลเหมือนกับการใช้เพียงครั้งเดียว ซึ่งช่วยในการจัดการการลองใหม่ได้อย่างราบรื่น แม้ว่าการคอมมิตบันทึกของ Raft ส่วนใหญ่จะรับประกันการใช้งานเพียงครั้งเดียวก็ตาม)
4. Commit Index
commitIndex คือดัชนีรายการบันทึกสูงสุดที่ทราบว่าคอมมิตแล้ว ซึ่งหมายความว่ารายการนั้นถูกจำลองอย่างปลอดภัยไปยังเซิร์ฟเวอร์ส่วนใหญ่และสามารถนำไปใช้กับเครื่องสถานะได้ ผู้นำเป็นผู้กำหนด commitIndex และผู้ติดตามจะอัปเดต commitIndex ตาม AppendEntries RPC ของผู้นำ รายการทั้งหมดจนถึง commitIndex ถือว่าถาวรและไม่สามารถย้อนกลับได้
5. Snapshot
เมื่อเวลาผ่านไป บันทึกที่จำลองอาจมีขนาดใหญ่มาก ทำให้เปลืองพื้นที่ดิสก์ และทำให้การจำลองบันทึกและการกู้คืนช้าลง Raft แก้ปัญหานี้ด้วย snapshots Snapshot คือการแสดงสถานะของเครื่องสถานะในเวลาที่กำหนดอย่างกะทัดรัด แทนที่จะเก็บทั้งบันทึก เซิร์ฟเวอร์สามารถสร้าง Snapshot ของสถานะเป็นระยะๆ ทิ้งรายการบันทึกทั้งหมดจนถึงจุด Snapshot และจากนั้นจำลอง Snapshot ไปยังผู้ติดตามใหม่หรือที่ล้าหลัง กระบวนการนี้ช่วยเพิ่มประสิทธิภาพได้อย่างมาก:
- Compact Log: ลดปริมาณข้อมูลบันทึกที่คงอยู่
- การกู้คืนที่เร็วขึ้น: เซิร์ฟเวอร์ใหม่หรือที่ขัดข้องสามารถรับ Snapshot แทนที่จะต้องเล่นบันทึกทั้งหมดตั้งแต่ต้น
-
InstallSnapshot RPC: Raft กำหนด
InstallSnapshotRPC เพื่อถ่ายโอน Snapshot จากผู้นำไปยังผู้ติดตาม
แม้จะมีประสิทธิภาพ แต่การสร้าง Snapshot ก็เพิ่มความซับซ้อนในการนำไปใช้ โดยเฉพาะอย่างยิ่งในการจัดการการสร้าง Snapshot แบบพร้อมกัน การตัดบันทึก และการถ่ายโอน
การนำ Raft ไปใช้: ข้อควรพิจารณาในการใช้งานจริงสำหรับการปรับใช้ทั่วโลก
การแปลการออกแบบที่สวยงามของ Raft ให้เป็นระบบที่แข็งแกร่งและพร้อมใช้งานจริง โดยเฉพาะอย่างยิ่งสำหรับผู้ชมทั่วโลกและโครงสร้างพื้นฐานที่หลากหลาย เกี่ยวข้องกับการแก้ไขความท้าทายทางวิศวกรรมในทางปฏิบัติหลายประการ
1. ความหน่วงแฝงของเครือข่ายและพาร์ติชั่นในบริบททั่วโลก
สำหรับระบบที่กระจายทั่วโลก ความหน่วงแฝงของเครือข่ายเป็นปัจจัยสำคัญ คลัสเตอร์ Raft โดยทั่วไปต้องการควอรุมของโหนดส่วนใหญ่เพื่อตกลงในรายการบันทึกก่อนที่จะคอมมิตได้ ในคลัสเตอร์ที่กระจายอยู่ทั่วทวีป ความหน่วงแฝงระหว่างโหนดอาจสูงถึงหลายร้อยมิลลิวินาที สิ่งนี้ส่งผลกระทบโดยตรงต่อ:
- Commit Latency: เวลาที่คำขอของไคลเอ็นต์จะคอมมิตอาจถูกจำกัดโดยลิงก์เครือข่ายที่ช้าที่สุดไปยังสำเนาส่วนใหญ่ กลยุทธ์ต่างๆ เช่น ผู้ติดตามแบบอ่านอย่างเดียว (ที่ไม่ต้องการการโต้ตอบกับผู้นำสำหรับการอ่านที่ล้าสมัย) หรือการกำหนดค่าควอรุมที่คำนึงถึงภูมิศาสตร์ (เช่น โหนด 3 โหนดในภูมิภาคหนึ่ง โหนด 2 โหนดในอีกภูมิภาคหนึ่งสำหรับคลัสเตอร์ 5 โหนด โดยที่ควอรุมอาจอยู่ในภูมิภาคที่รวดเร็วเพียงภูมิภาคเดียว) สามารถบรรเทาสิ่งนี้ได้
-
ความเร็วในการเลือกตั้งผู้นำ: ความหน่วงแฝงสูงอาจทำให้
RequestVoteRPCs ล่าช้า ส่งผลให้เกิดการแบ่งคะแนนบ่อยขึ้นหรือใช้เวลาเลือกตั้งนานขึ้น การปรับelection timeoutsให้มีค่ามากกว่าความหน่วงแฝงระหว่างโหนดทั่วไปเป็นสิ่งสำคัญ - การจัดการพาร์ติชั่นเครือข่าย: เครือข่ายในโลกแห่งความเป็นจริงมีแนวโน้มที่จะเกิดพาร์ติชั่น Raft จัดการพาร์ติชั่นได้อย่างถูกต้องโดยรับประกันว่าเฉพาะพาร์ติชั่นที่มีโหนดส่วนใหญ่เท่านั้นที่สามารถเลือกผู้นำและดำเนินการต่อไปได้ พาร์ติชั่นส่วนน้อยจะไม่สามารถคอมมิตรายการใหม่ได้ ดังนั้นจึงป้องกันสถานการณ์ split-brain อย่างไรก็ตาม พาร์ติชั่นที่ยืดเยื้อในสภาพแวดล้อมที่กระจายทั่วโลกอาจนำไปสู่การไม่พร้อมใช้งานในบางภูมิภาค ซึ่งจำเป็นต้องมีการตัดสินใจทางสถาปัตยกรรมอย่างรอบคอบเกี่ยวกับการวางควอรุม
2. ที่จัดเก็บข้อมูลถาวรและความทนทาน
ความถูกต้องของ Raft ขึ้นอยู่กับการคงอยู่ของบันทึกและสถานะอย่างมาก ก่อนที่เซิร์ฟเวอร์จะตอบสนองต่อ RPC หรือใช้รายการเข้ากับเครื่องสถานะ พวกเขาต้องตรวจสอบให้แน่ใจว่าข้อมูลที่เกี่ยวข้อง (รายการบันทึก current term votedFor) ถูกเขียนไปยังที่จัดเก็บที่เสถียรและ fsync'd (ล้างไปยังดิสก์) สิ่งนี้ป้องกันการสูญเสียข้อมูลในกรณีที่เกิดการขัดข้อง ข้อควรพิจารณา ได้แก่:
- ประสิทธิภาพ: การเขียนดิสก์บ่อยๆ อาจเป็นคอขวดด้านประสิทธิภาพ การรวมกลุ่มการเขียนและใช้ SSD ประสิทธิภาพสูงเป็นส่วนเพิ่มประสิทธิภาพทั่วไป
- ความน่าเชื่อถือ: การเลือกโซลูชันการจัดเก็บที่แข็งแกร่งและทนทาน (ดิสก์ภายในเครื่อง ที่จัดเก็บข้อมูลบนเครือข่าย ที่จัดเก็บข้อมูลแบบบล็อกคลาวด์) เป็นสิ่งสำคัญ
- WAL (Write-Ahead Log): บ่อยครั้ง การนำ Raft ไปใช้จะใช้ write-ahead log สำหรับความทนทาน คล้ายกับฐานข้อมูล เพื่อให้แน่ใจว่าการเปลี่ยนแปลงจะถูกเขียนไปยังดิสก์ก่อนที่จะถูกนำไปใช้ในหน่วยความจำ
3. การโต้ตอบกับไคลเอ็นต์และโมเดลความสอดคล้อง
ไคลเอ็นต์โต้ตอบกับคลัสเตอร์ Raft โดยส่งคำขอไปยังผู้นำ การจัดการคำขอของไคลเอ็นต์เกี่ยวข้องกับ:
- การค้นหาผู้นำ: ไคลเอ็นต์จำเป็นต้องมีกลไกในการค้นหาผู้นำปัจจุบัน สิ่งนี้สามารถทำได้ผ่านกลไกการค้นหาบริการ ปลายทางคงที่ที่เปลี่ยนเส้นทาง หรือโดยการลองเซิร์ฟเวอร์จนกว่าจะมีคนตอบกลับว่าเป็นผู้นำ
- การลองคำขอใหม่: ไคลเอ็นต์ต้องเตรียมพร้อมที่จะลองคำขอใหม่หากผู้นำเปลี่ยนแปลงหรือหากเกิดข้อผิดพลาดของเครือข่าย
-
การอ่านที่สอดคล้องกัน: Raft ส่วนใหญ่รับประกันความสอดคล้องที่แข็งแกร่งสำหรับการเขียน สำหรับการอ่าน มีหลายโมเดลที่เป็นไปได้:
- การอ่านที่สอดคล้องกันอย่างแข็งแกร่ง: ไคลเอ็นต์สามารถขอให้ผู้นำตรวจสอบว่าสถานะของตนทันสมัยหรือไม่ โดยการส่ง Heartbeat ไปยังผู้ติดตามส่วนใหญ่ก่อนที่จะให้บริการการอ่าน สิ่งนี้รับประกันความสดใหม่ แต่เพิ่มความหน่วงแฝง
- การอ่านแบบ Leader-Lease: ผู้นำสามารถรับ 'Lease' จากโหนดส่วนใหญ่เป็นระยะเวลาสั้นๆ ในระหว่างนั้นพวกเขารู้ว่าพวกเขายังคงเป็นผู้นำและสามารถให้บริการอ่านได้โดยไม่ต้องมีการบรรลุฉันทามติเพิ่มเติม สิ่งนี้เร็วกว่าแต่มีขีดจำกัดเวลา
- การอ่านที่ล้าสมัย (จากผู้ติดตาม): การอ่านโดยตรงจากผู้ติดตามสามารถให้ความหน่วงแฝงที่ต่ำลง แต่มีความเสี่ยงที่จะอ่านข้อมูลที่ล้าสมัยหากบันทึกของผู้ติดตามตามหลังผู้นำ สิ่งนี้เป็นที่ยอมรับสำหรับแอปพลิเคชันที่ความสอดคล้องในท้ายที่สุดเพียงพอสำหรับการอ่าน
4. การเปลี่ยนแปลงการกำหนดค่า (สมาชิกคลัสเตอร์)
การเปลี่ยนแปลงสมาชิกของคลัสเตอร์ Raft (การเพิ่มหรือลบเซิร์ฟเวอร์) เป็นการดำเนินการที่ซับซ้อนซึ่งต้องดำเนินการผ่านฉันทามติด้วยเพื่อหลีกเลี่ยงความไม่สอดคล้องกันหรือสถานการณ์ split-brain Raft นำเสนอเทคนิคที่เรียกว่า Joint Consensus:
- การกำหนดค่าสองแบบ: ระหว่างการเปลี่ยนแปลงการกำหนดค่า ระบบจะทำงานชั่วคราวด้วยการกำหนดค่าที่ทับซ้อนกันสองแบบ: การกำหนดค่าเก่า (C_old) และการกำหนดค่าใหม่ (C_new)
- สถานะ Joint Consensus (C_old, C_new): ผู้นำจะเสนอรายการบันทึกพิเศษที่แสดงถึงการกำหนดค่าร่วม เมื่อรายการนี้คอมมิตแล้ว (ต้องการความเห็นชอบจากควอรุมใน C_old และ C_new ทั้งสอง) ระบบจะอยู่ในสถานะเปลี่ยนผ่าน ตอนนี้การตัดสินใจต้องการควอรุมจากทั้งสองการกำหนดค่า สิ่งนี้ทำให้มั่นใจได้ว่าในช่วงเปลี่ยนผ่าน ทั้งการกำหนดค่าเก่าหรือใหม่ไม่สามารถตัดสินใจฝ่ายเดียวได้ ป้องกันการแยกย่อย
- การเปลี่ยนไปเป็น C_new: เมื่อรายการบันทึกการกำหนดค่าร่วมคอมมิตแล้ว ผู้นำจะเสนอรายการบันทึกอีกรายการหนึ่งที่แสดงเฉพาะการกำหนดค่าใหม่ (C_new) เมื่อรายการที่สองนี้คอมมิตแล้ว การกำหนดค่าเก่าจะถูกทิ้ง และระบบจะทำงานภายใต้ C_new เท่านั้น
- ความปลอดภัย: กระบวนการแบบสองเฟสเหมือนการคอมมิตนี้ทำให้มั่นใจได้ว่า ณ จุดใดจุดหนึ่ง จะไม่มีผู้นำที่ขัดแย้งกันสองคนได้รับการเลือกตั้ง (คนหนึ่งภายใต้ C_old คนหนึ่งภายใต้ C_new) และระบบยังคงทำงานตลอดการเปลี่ยนแปลง
การนำการเปลี่ยนแปลงการกำหนดค่าไปใช้อย่างถูกต้องเป็นส่วนที่ท้าทายที่สุดส่วนหนึ่งของการนำ Raft ไปใช้ เนื่องมาจากกรณีพิเศษและสถานการณ์ความล้มเหลวมากมายในช่วงเปลี่ยนผ่าน
5. การทดสอบระบบแบบกระจาย: แนวทางที่เข้มงวด
การทดสอบอัลกอริทึมฉันทามติแบบกระจายเช่น Raft เป็นเรื่องท้าทายอย่างยิ่งเนื่องจากธรรมชาติที่ไม่กำหนดและโหมดความล้มเหลวที่หลากหลาย การทดสอบหน่วยง่ายๆ ไม่เพียงพอ การทดสอบที่เข้มงวดเกี่ยวข้องกับ:
- การฉีดข้อผิดพลาด: การแนะนำความล้มเหลวอย่างเป็นระบบ เช่น การขัดข้องของโหนด พาร์ติชั่นเครือข่าย การหน่วงเวลาข้อความ และการจัดลำดับข้อความใหม่ เครื่องมือเช่น Jepsen ถูกออกแบบมาเพื่อวัตถุประสงค์นี้โดยเฉพาะ
- การทดสอบตามคุณสมบัติ: การกำหนดอินแวเรียนต์และคุณสมบัติด้านความปลอดภัย (เช่น ผู้นำไม่เกินหนึ่งคนต่อเทอม รายการที่คอมมิตจะไม่สูญหาย) และทดสอบว่าการนำไปใช้เป็นไปตามคุณสมบัติเหล่านี้ภายใต้เงื่อนไขต่างๆ
- Model Checking: สำหรับส่วนสำคัญของอัลกอริทึม เทคนิคการตรวจสอบอย่างเป็นทางการสามารถใช้เพื่อพิสูจน์ความถูกต้อง แต่นี่เป็นสิ่งที่เชี่ยวชาญมาก
- สภาพแวดล้อมจำลอง: การรันการทดสอบในสภาพแวดล้อมที่จำลองเงื่อนไขเครือข่าย (ความหน่วงแฝง การสูญเสียแพ็คเก็ต) ที่เป็นลักษณะของการปรับใช้ทั่วโลก
กรณีการใช้งานและการใช้งานจริง
การใช้งานได้จริงและความสามารถในการทำความเข้าใจของ Raft ได้นำไปสู่การนำไปใช้อย่างแพร่หลายในส่วนประกอบโครงสร้างพื้นฐานที่สำคัญต่างๆ:
1. ที่เก็บข้อมูล Key-Value แบบกระจายและการจำลองฐานข้อมูล
- etcd: ส่วนประกอบพื้นฐานของ Kubernetes, etcd ใช้ Raft เพื่อจัดเก็บและจำลองข้อมูลการกำหนดค่า ข้อมูลการค้นหาบริการ และจัดการสถานะของคลัสเตอร์ ความน่าเชื่อถือเป็นสิ่งสำคัญอย่างยิ่งเพื่อให้ Kubernetes ทำงานได้อย่างถูกต้อง
- Consul: พัฒนาโดย HashiCorp, Consul ใช้ Raft สำหรับแบ็กเอนด์การจัดเก็บแบบกระจาย ทำให้สามารถค้นหาบริการ การตรวจสอบสถานะ และการจัดการการกำหนดค่าในสภาพแวดล้อมโครงสร้างพื้นฐานแบบไดนามิก
- TiKV: ที่เก็บข้อมูล key-value แบบกระจายที่รองรับธุรกรรม ซึ่งใช้โดย TiDB (ฐานข้อมูล SQL แบบกระจาย) ใช้ Raft สำหรับการจำลองข้อมูลและการรับประกันความสอดคล้อง
- CockroachDB: ฐานข้อมูล SQL แบบกระจายทั่วโลกนี้ใช้ Raft อย่างกว้างขวางสำหรับการจำลองข้อมูลข้ามโหนดและภูมิภาคต่างๆ เพื่อรับประกันความพร้อมใช้งานสูงและความสอดคล้องที่แข็งแกร่ง แม้จะมีความล้มเหลวทั่วทั้งภูมิภาค
2. การค้นหาบริการและการจัดการการกำหนดค่า
Raft มอบรากฐานที่เหมาะสมสำหรับระบบที่ต้องการจัดเก็บและแจกจ่ายข้อมูลเมตาที่สำคัญเกี่ยวกับบริการและการกำหนดค่าข้ามคลัสเตอร์ เมื่อบริการลงทะเบียนหรือการกำหนดค่าเปลี่ยนแปลง Raft จะรับประกันว่าโหนดทั้งหมดจะเห็นพ้องกันในที่สุดเกี่ยวกับสถานะใหม่ ซึ่งช่วยให้สามารถอัปเดตแบบไดนามิกโดยไม่ต้องมีการแทรกแซงด้วยตนเอง
3. ผู้ประสานงานธุรกรรมแบบกระจาย
สำหรับระบบที่ต้องการความเป็นอะตอมข้ามการดำเนินการหรือบริการหลายรายการ Raft สามารถสนับสนุนผู้ประสานงานธุรกรรมแบบกระจาย โดยรับประกันว่าบันทึกธุรกรรมจะถูกจำลองอย่างสอดคล้องกันก่อนที่จะคอมมิตการเปลี่ยนแปลงข้ามผู้เข้าร่วม
4. การประสานงานคลัสเตอร์และการเลือกผู้นำในระบบอื่นๆ
นอกเหนือจากการใช้งานฐานข้อมูลหรือที่เก็บข้อมูล Key-Value อย่างชัดเจน Raft มักจะถูกฝังเป็นไลบรารีหรือส่วนประกอบหลักเพื่อจัดการงานประสานงาน เลือกผู้นำสำหรับกระบวนการแบบกระจายอื่นๆ หรือจัดหาเครื่องบินควบคุมที่เชื่อถือได้ในระบบที่ใหญ่ขึ้น ตัวอย่างเช่น โซลูชันคลาวด์เนทีฟหลายแห่งใช้ Raft ในการจัดการสถานะของส่วนประกอบเครื่องบินควบคุม
ข้อดีข้อเสียของ Raft
แม้ว่า Raft จะมีประโยชน์อย่างมาก แต่ก็จำเป็นต้องเข้าใจการแลกเปลี่ยน
ข้อดี:
- ความสามารถในการทำความเข้าใจ: เป้าหมายการออกแบบหลัก ทำให้ง่ายต่อการนำไปใช้ แก้ไขข้อบกพร่อง และให้เหตุผลมากกว่าอัลกอริทึมฉันทามติรุ่นเก่าเช่น Paxos
- ความสอดคล้องที่แข็งแกร่ง: ให้การรับประกันความสอดคล้องที่แข็งแกร่งสำหรับรายการบันทึกที่คอมมิต ทำให้มั่นใจได้ถึงความสมบูรณ์ของข้อมูลและความน่าเชื่อถือ
-
ความทนทานต่อข้อผิดพลาด: สามารถทนทานต่อความล้มเหลวของโหนดส่วนน้อย (สูงสุด
(N-1)/2ความล้มเหลวในคลัสเตอร์Nโหนด) โดยไม่สูญเสียความพร้อมใช้งานหรือความสอดคล้อง - ประสิทธิภาพ: ในสภาวะที่เสถียร (ไม่มีการเปลี่ยนแปลงผู้นำ) Raft สามารถบรรลุปริมาณงานสูงได้เนื่องจากผู้นำประมวลผลคำขอทั้งหมดตามลำดับและจำลองแบบขนาน ใช้แบนด์วิดท์เครือข่ายอย่างมีประสิทธิภาพ
- บทบาทที่กำหนดไว้อย่างชัดเจน: บทบาทที่ชัดเจน (ผู้นำ ผู้ติดตาม ผู้สมัคร) และการเปลี่ยนสถานะช่วยลดความซับซ้อนของแบบจำลองความคิดและการนำไปใช้
- การเปลี่ยนแปลงการกำหนดค่า: นำเสนอกลไกที่แข็งแกร่ง (Joint Consensus) สำหรับการเพิ่มหรือลบโหนดออกจากคลัสเตอร์อย่างปลอดภัยโดยไม่กระทบต่อความสอดคล้อง
ข้อเสีย:
- คอขวดของผู้นำ: คำขอเขียนของไคลเอ็นต์ทั้งหมดต้องผ่านผู้นำ ในสถานการณ์ที่มีปริมาณงานเขียนสูงมากหรือเมื่อผู้นำอยู่ห่างไกลจากไคลเอ็นต์ทางภูมิศาสตร์ สิ่งนี้อาจกลายเป็นคอขวดด้านประสิทธิภาพ
- ความหน่วงแฝงในการอ่าน: การอ่านที่สอดคล้องกันอย่างแข็งแกร่งมักต้องการการสื่อสารกับผู้นำ ซึ่งอาจเพิ่มความหน่วงแฝง การอ่านจากผู้ติดตามมีความเสี่ยงที่จะอ่านข้อมูลที่ล้าสมัย
- ข้อกำหนดควอรุม: ต้องการโหนดส่วนใหญ่ที่พร้อมใช้งานสำหรับการคอมมิตรายการใหม่ ในคลัสเตอร์ 5 โหนด สามารถทนต่อความล้มเหลว 2 ครั้ง หากโหนด 3 โหนดล้มเหลว คลัสเตอร์จะไม่สามารถดำเนินการเขียนได้ สิ่งนี้อาจเป็นเรื่องท้าทายในสภาพแวดล้อมที่มีพาร์ติชั่นสูงหรือกระจายไปทั่วโลก ซึ่งการรักษาควอรุมข้ามภูมิภาคเป็นเรื่องยาก
- ความอ่อนไหวต่อเครือข่าย: ไวต่อความหน่วงแฝงของเครือข่ายและพาร์ติชั่นอย่างมาก ซึ่งอาจส่งผลต่อเวลาการเลือกตั้งและปริมาณงานของระบบโดยรวม โดยเฉพาะอย่างยิ่งในการใช้งานที่กระจายอย่างกว้างขวาง
- ความซับซ้อนของการเปลี่ยนแปลงการกำหนดค่า: แม้ว่าจะแข็งแกร่ง แต่กลไก Joint Consensus เป็นหนึ่งในส่วนที่ซับซ้อนที่สุดของอัลกอริทึม Raft ที่จะต้องนำไปใช้อย่างถูกต้องและทดสอบอย่างละเอียด
- จุดล้มเหลวเดียว (สำหรับการเขียน): แม้ว่าจะทนทานต่อความล้มเหลวของผู้นำ หากผู้นำไม่สามารถทำงานได้ถาวรและไม่สามารถเลือกผู้นำคนใหม่ได้ (เช่น เนื่องจากพาร์ติชั่นเครือข่ายหรือความล้มเหลวมากเกินไป) ระบบจะไม่สามารถดำเนินการเขียนได้
บทสรุป: การเป็นผู้เชี่ยวชาญด้านการบรรลุฉันทามติแบบกระจายสำหรับระบบทั่วโลกที่ยืดหยุ่น
อัลกอริทึม Raft เป็นเครื่องพิสูจน์ถึงพลังของการออกแบบที่รอบคอบในการแก้ปัญหาที่ซับซ้อน การเน้นที่ความสามารถในการทำความเข้าใจของ Raft ได้ทำให้การบรรลุฉันทามติแบบกระจายเข้าถึงได้มากขึ้น ทำให้ผู้พัฒนาและองค์กรจำนวนมากขึ้นสามารถสร้างระบบที่มีความพร้อมใช้งานสูงและทนทานต่อข้อผิดพลาดได้โดยไม่ต้องตกอยู่ภายใต้ความซับซ้อนที่เข้าใจยากของวิธีการก่อนหน้านี้
ตั้งแต่การจัดการคลัสเตอร์คอนเทนเนอร์ด้วย Kubernetes (ผ่าน etcd) ไปจนถึงการจัดเก็บข้อมูลที่ยืดหยุ่นสำหรับฐานข้อมูลทั่วโลกเช่น CockroachDB, Raft เป็นแรงขับเคลื่อนที่ทำงานเงียบๆ ทำให้โลกดิจิทัลของเรายังคงสอดคล้องกันและทำงานได้ การนำ Raft ไปใช้ไม่ใช่เรื่องง่าย แต่ความชัดเจนของข้อกำหนดและระบบนิเวศที่หลากหลายที่ล้อมรอบทำให้เป็นความพยายามที่คุ้มค่าสำหรับผู้ที่มุ่งมั่นที่จะสร้างระบบโครงสร้างพื้นฐานที่แข็งแกร่งและปรับขนาดได้รุ่นต่อไป
ข้อมูลเชิงลึกที่ดำเนินการได้สำหรับนักพัฒนาและสถาปนิก:
- ให้ความสำคัญกับความเข้าใจ: ก่อนที่จะพยายามนำไปใช้ ให้ลงทุนเวลาในการทำความเข้าใจกฎและสถานะการเปลี่ยนผ่านแต่ละข้อของ Raft อย่างละเอียด กระดาษต้นฉบับและคำอธิบายแบบภาพมีประโยชน์อย่างยิ่ง
- ใช้ประโยชน์จากไลบรารีที่มีอยู่: สำหรับแอปพลิเคชันส่วนใหญ่ ให้พิจารณาใช้การนำ Raft ไปใช้ที่มีอยู่ซึ่งได้รับการตรวจสอบแล้ว (เช่น จาก etcd, ไลบรารี Raft ของ HashiCorp) แทนที่จะสร้างตั้งแต่ต้น เว้นแต่ข้อกำหนดของคุณจะมีความเฉพาะเจาะจงสูง หรือคุณกำลังดำเนินการวิจัยทางวิชาการ
- การทดสอบที่เข้มงวดเป็นสิ่งที่จำเป็น: การฉีดข้อผิดพลาด การทดสอบตามคุณสมบัติ และการจำลองสถานการณ์ความล้มเหลวอย่างกว้างขวางเป็นสิ่งสำคัญสำหรับระบบฉันทามติแบบกระจายใดๆ อย่าสันนิษฐานว่า "ทำงานได้" โดยไม่พยายามทำให้พังอย่างละเอียด
- ออกแบบสำหรับความหน่วงแฝงทั่วโลก: เมื่อปรับใช้ทั่วโลก ให้พิจารณาการวางควอรุม โทโพโลยีเครือข่าย และกลยุทธ์การอ่านของไคลเอ็นต์อย่างรอบคอบ เพื่อปรับให้เหมาะสมกับทั้งความสอดคล้องและประสิทธิภาพในภูมิภาคทางภูมิศาสตร์ต่างๆ
-
การคงอยู่และความทนทาน: ตรวจสอบให้แน่ใจว่าเลเยอร์การจัดเก็บข้อมูลพื้นฐานของคุณแข็งแกร่ง และ
fsyncหรือการดำเนินการเทียบเท่าถูกใช้อย่างถูกต้องเพื่อป้องกันการสูญเสียข้อมูลในสถานการณ์ที่เกิดการขัดข้อง
ในขณะที่ระบบแบบกระจายยังคงวิวัฒนาการ หลักการที่ Raft นำมาใช้—ความชัดเจน ความแข็งแกร่ง และความทนทานต่อข้อผิดพลาด—จะยังคงเป็นรากฐานของการสร้างซอฟต์แวร์ที่เชื่อถือได้ การเป็นผู้เชี่ยวชาญ Raft คุณจะได้รับเครื่องมืออันทรงพลังในการสร้างแอปพลิเคชันที่ยืดหยุ่นและปรับขนาดได้ทั่วโลกซึ่งสามารถทนทานต่อความสับสนที่หลีกเลี่ยงไม่ได้ของการประมวลผลแบบกระจาย