ฉันลงมือเขียนอัลกอริทึมฉันทามติ Raft (ตัวอย่างชูโรงของอัลกอริทึมแบบกระจาย) ด้วย Python เป็นโค้ดที่เขียนได้แย่ทีเดียว! แต่ก็ทำงานถูกต้อง (ในระดับหนึ่ง) ด้วย
ต่อไปนี้คือข้อสังเกตที่ฉันอยากแบ่งปันกับใครก็ตามที่สนใจลองความท้าทายคล้ายกันนี้
เมื่อมองย้อนกลับไป แหล่งข้อมูลต่อไปนี้มีประโยชน์มากที่สุดในการเรียนรู้เรื่อง Raft และเขียนให้ถูกต้อง
- บทความวิจัย Raft (อ่านจนถึงส่วนที่ 5 และอ้างอิงรูปที่ 2 บ่อย ๆ)
- คู่มือ Raft สำหรับนักศึกษา
- หนึ่งในโค้ด Raft ที่มีการใช้งานแพร่หลายที่สุด
- โคลนรีโพซิทอรี อ่าน
raft.goคร่าว ๆ แล้วคุยโต้ตอบกับ LLM เพื่อทำความเข้าใจชุดโค้ดและเหตุผลเบื้องหลังการออกแบบ
- โคลนรีโพซิทอรี อ่าน
- บทความชุดในบล็อกของ Eli Bendersky
ฉันแนะนำให้ใช้เวลาสักชั่วโมงอ่านบทความวิจัยก่อน จากนั้นค่อยเขียนโค้ดโครงร่างสำหรับเซิร์ฟเวอร์ UDP หรือ TCP ที่อ่านไบต์ขาเข้าแล้วเพิ่มลงในอาร์เรย์ จากนั้นฉันก็ค่อย ๆ ทำตามโค้ดของ Eli โดยเพิ่มฟีเจอร์ให้โค้ด Raft ของฉันตามลำดับเดียวกัน
หลังจากทำให้กระบวนการที่ดูเหมือนการเลือกผู้นำทำงานได้ ฉันก็เริ่มหาบั๊กและจุดที่ตัวเองเข้าใจอัลกอริทึมผิด ฉันสลับไปมาระหว่างคู่มือสำหรับนักศึกษา รูปที่ 2 ในบทความวิจัย Raft และโค้ดของฉัน โดยคิดอย่างรอบคอบว่าโค้ดของฉันตรงกับคำอธิบายเหล่านั้น (หรือแตกต่างออกไป) ตรงไหน ฉันยังพึ่ง LLM ช่วยตรวจทานโค้ดนี้อยู่มาก โดยใส่เนื้อหาจากแหล่งข้อมูลข้างต้นลงไปในบริบทด้วย
ทำขั้นตอนข้างต้นซ้ำกับการจำลองแบบล็อก การเก็บข้อมูลถาวร ฯลฯ
ว่าด้วยการลงมือเขียน
ฉันเลือกออกแบบบางอย่างให้เรียบง่ายลงในโค้ดของฉัน โดยไม่ได้เรียงลำดับเป็นพิเศษ:
- แต่ละโหนดทำงานและประมวลผลข้อความบนเธรดเดียว
- ใช้ "นาฬิกาเชิงตรรกะ" เพื่อติดตาม "เวลา" ภายในแต่ละโหนดของระบบ (เช่น เรียก
tick()แล้วเพิ่มค่าตัวนับภายในแต่ละโหนด แทนการใช้เวลาของระบบ) - "ทำให้โค้ดยุ่งเหยิง" ด้วยการรวมทุกอย่างไว้ในไฟล์เดียว เช่น การแยกวิเคราะห์ข้อมูลจากเครือข่าย การจัดเก็บข้อมูล/การเก็บข้อมูลถาวร อัลกอริทึมหลักของ Raft และยูทิลิตี/คำสั่งสำหรับควบคุมตัวโหนดเอง
ข้อ 2 ดูเป็นทางเลือกในการออกแบบที่สมเหตุสมผลและถูกต้อง (โค้ดของ etcd ก็ใช้นาฬิกาเชิงตรรกะ) ข้อ 3 ก็พอจะกล่าวได้ว่าดีกว่าสำหรับการเรียนรู้/การสอน การรวมทุกอย่างไว้ในไฟล์เดียวก็ดีตรงที่มองเห็นทั้งหมดได้ในคราวเดียว และยังได้โค้ดที่สะดวกจะรื้อมาลองดูว่า abstraction แบบไหนเข้ากับอัลกอริทึมได้ดีที่สุด
สำหรับฉัน ข้อ 1 เป็นทางเลือกที่ดูผิดหลักอยู่สักหน่อย มันช่วยให้เขียนโค้ดได้ง่ายขึ้นมากจริง ๆ (ต้องกังวลน้อยลงเรื่องการเกิด deadlock และการอัปเดตสถานะภายในของโหนดแบบอะตอมมิก) แต่สุดท้ายสิ่งที่ได้ก็ยังไม่ใช่ Raft เสียทีเดียว สำหรับการเขียนครั้งแรก แบบนี้ก็ดูจะไม่เป็นไร อัลกอริทึมนี้ซับซ้อนพออยู่แล้ว และฉันคิดว่าคุณน่าจะอยากใช้เวลาไปกับการดีบักข้อผิดพลาดเชิงตรรกะในอัลกอริทึมหลักของ Raft มากกว่ามัววุ่นวายกับ mutex
ฉันมองว่าการเขียน Raft ด้วยวิธีนี้เป็นโครงการที่ใช้เวลาประมาณ 30 ชั่วโมง การอ่านบทความวิจัย Raft ในช่วงแรกและทบทวนเนื้อหาที่เกี่ยวข้องน่าจะใช้เวลาสองสามชั่วโมง ฉันเขียนโค้ดส่วนใหญ่ในช่วงวันหยุดโดยใช้เวลาประมาณ 3 วัน นั่งเขียนวันละประมาณ 6-8 ชั่วโมง ฉันยังมีจุดที่ต้องเก็บรายละเอียดและปรับปรุงในโค้ดที่มีอยู่ (เช่น แก้บั๊กที่สังเกตได้ยากบางจุด) ซึ่งอาจต้องใช้เวลาทำงานอีกครึ่งวัน
โดยรวมแล้ว ก็ถือว่าไม่แย่เลยสำหรับการทำความเข้าใจหนึ่งในอัลกอริทึมหลักที่ขับเคลื่อน สารพัด ระบบโครงสร้างพื้นฐาน