Raft mutabakat algoritmasını (dağıtık algoritmaların gözde örneğini) Python ile kodladım. Ortaya çıkan uygulama epey kötü! Ama aynı zamanda (bir ölçüde) doğru.
Benzer bir işe girişmek isteyen herkesle paylaşabileceğim birkaç not var.
Geriye dönüp baktığımda, Raft’ı öğrenmek ve doğru biçimde kodlamak için en yararlı kaynaklar şunlardı.
- Raft makalesi (5. bölüme kadar okuyun ve Şekil 2’ye sık sık başvurun)
- Öğrenciler İçin Raft Rehberi
- en yaygın kullanılan Raft uygulamalarından biri
- depoyu klonlayın,
raft.goiçeriğine göz gezdirin ve kod tabanını ve tasarım kararlarını anlamak için bir LLM ile karşılıklı konuşun
- depoyu klonlayın,
- Eli Bendersky’nin blog yazı dizisi
Önce makaleyi okumaya bir saat kadar ayırmanızı, ardından gelen baytları okuyup bir diziye ekleyen bir UDP veya TCP sunucusu için kod iskeleti oluşturmanızı öneririm. Ben daha sonra Eli’nin uygulamasını takip ederek kendi Raft uygulamama özellikleri aynı sırayla ekledim.
Seçime benzer bir işleyişi çalışır hâle getirdikten sonra, hataları ve algoritmayı yanlış anladığım noktaları aramaya başladım. Öğrenci rehberi, Raft makalesindeki Şekil 2 ve kendi uygulamam arasında gidip gelerek uygulamamın nerelerde aynı olduğunu (veya farklılaştığını) dikkatle değerlendiriyordum. Bu kodu gözden geçirmek için bir LLM’den de yoğun biçimde yararlandım; yukarıdaki kaynaklardan içerikleri bağlama ekledim.
Günlük çoğaltma, kalıcılık vb. için yukarıdaki süreci tekrarlayın.
uygulamaya dair
Uygulamamda tasarımı basitleştiren bazı tercihler yaptım. Belirli bir sıralama olmaksızın:
- her düğüm tek bir iş parçacığında çalışır ve mesajları işler
- sistemdeki yerel "zamanı" takip etmek için bir "mantıksal saat" kullanmak (ör. sistem saatini kullanmak yerine
tick()çağrısı yapıp her düğüme ait yerel bir sayacı artırmak) - her şeyi tek bir dosyada tutarak uygulamayı "karıştırmak"; ör. ağ verilerinin ayrıştırılması, depolama/kalıcılık, temel Raft algoritması ve düğümün kendisini kontrol etmeye yarayan yardımcı araçlar/komutlar
2, sağlam ve doğru bir tasarım tercihi gibi görünüyor (etcd’nin uygulamasında mantıksal saatler kullanılıyor). 3’ün öğrenme/öğretim açısından daha iyi olduğu savunulabilir. Her şeyi tek bir dosyada tutmak güzel; böylece hepsini aynı anda görebiliyorsunuz. Ayrıca, parçalara ayırıp hangi soyutlamaların algoritmaya en iyi uyduğunu görebileceğiniz güzel bir uygulamanız oluyor.
1 ise bana biraz aşırıya kaçan bir tercih gibi geliyor. Uygulamayı çok daha basit hâle getiriyor (karşılıklı kilitlenmelere ve düğümün iç durumunu atomik olarak güncellemeye daha az kafa yoruyorsunuz), ama sonunda ortaya tam olarak Raft sayılmayacak bir şey çıkıyor. İlk uygulama için bu makul görünüyor. Algoritma zaten yeterince karmaşık ve bence zamanınızı mutex’lerle uğraşmak yerine temel Raft algoritmasındaki mantık hatalarını ayıklamaya harcamayı tercih edersiniz.
Raft’ı bu şekilde kodlamayı ~30 saatlik bir proje olarak değerlendiririm. Raft makalesini ilk kez okumak ve ilgili kaynakları incelemek birkaç saat sürmeli. Kodlamanın büyük bölümünü tatil döneminde, günde yaklaşık 6-8 saat çalışarak ~3 günde yaptım. Mevcut uygulamada hâlâ elden geçirmem ve iyileştirmem gereken bazı şeyler var (ör. fark edilmesi zor bazı hataları düzeltmek); bunlar da yarım gün daha çalışma gerektirebilir.
Genel olarak, güç verdiği bunca altyapı düşünüldüğünde, temel algoritmalardan birini anlamak için hiç de fena değil.