Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Memahami Pelaksanaan Rakit etcd: Penyelaman Mendalam ke Log Rakit

Memahami Pelaksanaan Rakit etcd: Penyelaman Mendalam ke Log Rakit

Mary-Kate Olsen
Mary-Kate Olsenasal
2024-11-23 06:14:17146semak imbas

pengenalan

Artikel ini akan memperkenalkan dan menganalisis reka bentuk dan pelaksanaan modul Raft Log dalam Raft etcd, bermula daripada log dalam algoritma konsensus Raft. Matlamatnya adalah untuk membantu pembaca lebih memahami pelaksanaan Rakit etcd dan menyediakan pendekatan yang mungkin untuk melaksanakan senario yang serupa.

Gambaran Keseluruhan Log Rakit

Algoritma konsensus Raft pada dasarnya ialah mesin keadaan yang direplikasi, dengan matlamat untuk mereplikasi satu siri log dengan cara yang sama merentas kluster pelayan. Log ini membolehkan pelayan dalam kelompok mencapai keadaan yang konsisten.

Dalam konteks ini, log merujuk kepada Log Rakit. Setiap nod dalam kluster mempunyai Log Rakit sendiri, yang terdiri daripada satu siri entri log. Entri log biasanya mengandungi tiga medan:

  • Indeks: Indeks entri log
  • Syarat: Istilah ketua apabila entri log dibuat
  • Data: Data yang terkandung dalam entri log, yang boleh menjadi arahan khusus, dsb.

Adalah penting untuk ambil perhatian bahawa indeks Log Rakit bermula pada 1, dan hanya nod ketua boleh mencipta dan mereplikasi Log Rakit kepada nod pengikut.

Apabila entri log disimpan secara berterusan pada majoriti nod dalam kelompok (cth., 2/3, 3/5, 4/7), ia dianggap komit.

Apabila entri log digunakan pada mesin keadaan, ia dianggap digunakan.

Understanding etcd

gambaran keseluruhan pelaksanaan rakit etcd

etcd raft ialah perpustakaan algoritma Raft yang ditulis dalam Go, digunakan secara meluas dalam sistem seperti etcd, Kubernetes, CockroachDB dan lain-lain.

Ciri utama rakit etcd ialah ia hanya melaksanakan bahagian teras algoritma Raft. Pengguna mesti melaksanakan penghantaran rangkaian, storan cakera dan komponen lain yang terlibat dalam proses Raft itu sendiri (walaupun etcd menyediakan pelaksanaan lalai).

Berinteraksi dengan perpustakaan rakit etcd agak mudah: ia memberitahu anda data yang perlu diteruskan dan mesej yang perlu dihantar ke nod lain. Tanggungjawab anda adalah untuk mengendalikan penyimpanan dan proses penghantaran rangkaian dan memaklumkannya dengan sewajarnya. Ia tidak membimbangkan dirinya dengan butiran cara anda melaksanakan operasi ini; ia hanya memproses data yang anda serahkan dan, berdasarkan algoritma Raft, memberitahu anda langkah seterusnya.

Dalam pelaksanaan kod rakit etcd, model interaksi ini digabungkan dengan lancar dengan ciri saluran unik Go, menjadikan perpustakaan rakit etcd benar-benar tersendiri.

Cara Melaksanakan Log Rakit

log dan log_tidak stabil

Dalam etcd raft, pelaksanaan utama Raft Log terletak dalam fail log.go dan log_unstable.go, dengan struktur utama ialah raftLog dan tidak stabil. Struktur yang tidak stabil juga merupakan medan dalam raftLog.

  • raftLog bertanggungjawab ke atas logik utama Raft Log. Ia boleh mengakses keadaan storan log nod melalui antara muka Storan yang diberikan kepada pengguna.
  • tidak stabil, seperti namanya, mengandungi entri log yang belum diteruskan lagi, bermakna log tidak komited.

etcd raft menguruskan log dalam algoritma dengan menyelaraskan raftLog dan tidak stabil.

Medan Teras raftLog dan tidak stabil

Untuk memudahkan perbincangan, artikel ini akan menumpukan hanya pada logik pemprosesan entri log, tanpa menangani pengendalian syot kilat dalam rakit etcd.

type raftLog struct {
    storage Storage
    unstable unstable
    committed uint64
    applying uint64
    applied uint64
}

Bidang teras raftLog:

  • storan: Antara muka storan yang dilaksanakan oleh pengguna, digunakan untuk mendapatkan semula entri log yang telah dikekalkan.
  • tidak stabil: Menyimpan log yang tidak berterusan. Contohnya, apabila Pemimpin menerima permintaan daripada pelanggan, ia mencipta entri log dengan Termanya dan menambahkannya pada log yang tidak stabil.
  • komited: Dikenali sebagai commitIndex dalam kertas Raft, ia mewakili indeks entri log komited terakhir yang diketahui.
  • memohon: Indeks tertinggi entri log yang sedang digunakan.
  • diguna pakai: Dikenali sebagai lastApplied dalam kertas Raft, ia adalah indeks tertinggi entri log yang telah digunakan pada mesin keadaan.
type unstable struct {
    entries []pb.Entry
    offset uint64
    offsetInProgress uint64
}

Bidang teras tidak stabil:

  • Entri: Entri log yang tidak berterusan, disimpan dalam ingatan sebagai kepingan.
  • offset: Digunakan untuk memetakan entri log dalam entri ke Log Rakit, di mana entri[i] = Log Rakit[i mengimbangi].
  • offsetInProgress: Menunjukkan entri yang sedang diteruskan. Entri yang sedang dijalankan diwakili oleh entri[:offsetInProgress-offset].

Medan teras dalam raftLog adalah mudah dan boleh dikaitkan dengan pelaksanaan dalam kertas Raft. Walau bagaimanapun, medan dalam tidak stabil mungkin kelihatan lebih abstrak. Contoh berikut bertujuan untuk membantu menjelaskan konsep ini.

Anggapkan kami sudah mempunyai 5 entri log kekal dalam Log Rakit kami. Kini, kami mempunyai 3 entri log yang disimpan dalam tidak stabil, dan 3 entri log ini sedang diteruskan. Keadaannya adalah seperti di bawah:

Understanding etcd

offset=6 menunjukkan bahawa entri log pada kedudukan 0, 1, dan 2 dalam tidak stabil. entri sepadan dengan kedudukan 6 (0 6), 7 (1 6), dan 8 (2 6) dalam Log Rakit sebenar. Dengan offsetInProgress=9, kita tahu bahawa unstable.entry[:9-6], yang merangkumi tiga entri log pada kedudukan 0, 1 dan 2, semuanya berterusan.

Sebab offset dan offsetInProgress digunakan dalam tidak stabil ialah unstable tidak menyimpan semua entri Log Rakit.

Bila Berinteraksi

Memandangkan kami hanya menumpukan pada logik pemprosesan Log Rakit, "bila hendak berinteraksi" di sini merujuk kepada bila rakit etcd akan melepasi entri log yang perlu diteruskan oleh pengguna.

Bahagian Pengguna

etcd raft berinteraksi dengan pengguna terutamanya melalui kaedah dalam antara muka Nod. Kaedah Sedia mengembalikan saluran yang membolehkan pengguna menerima data atau arahan daripada rakit etcd.

type raftLog struct {
    storage Storage
    unstable unstable
    committed uint64
    applying uint64
    applied uint64
}

Struktur Sedia yang diterima daripada saluran ini mengandungi entri log yang memerlukan pemprosesan, mesej yang harus dihantar ke nod lain, keadaan semasa nod dan banyak lagi.

Untuk perbincangan kami tentang Raft Log, kami hanya perlu menumpukan pada medan Entri dan CommittedEntries:

  • Entri: Log masukan yang perlu diteruskan. Setelah entri ini diteruskan, ia boleh diambil semula menggunakan antara muka Storan.
  • CommittedEntries: Log masukan yang perlu digunakan pada mesin keadaan.
type unstable struct {
    entries []pb.Entry
    offset uint64
    offsetInProgress uint64
}

Selepas memproses log, mesej dan data lain yang dihantar melalui Sedia, kami boleh memanggil kaedah Advance dalam antara muka Nod untuk memaklumkan rakit etcd bahawa kami telah menyelesaikan arahannya, membenarkannya menerima dan memproses Sedia seterusnya.

etcd raft menawarkan pilihan AsyncStorageWrites, yang boleh meningkatkan prestasi nod sedikit sebanyak. Walau bagaimanapun, kami tidak mempertimbangkan pilihan ini di sini.

etcd rakit Sisi

Di sisi pengguna, tumpuan adalah pada pengendalian data dalam struktur Sedia yang diterima. Di bahagian rakit etcd, tumpuan adalah pada menentukan masa untuk menghantar struct Sedia kepada pengguna dan tindakan yang perlu diambil selepas itu.

Saya telah meringkaskan kaedah utama yang terlibat dalam proses ini dalam rajah berikut, yang menunjukkan urutan umum panggilan kaedah (perhatikan bahawa ini hanya mewakili anggaran tertib panggilan):

Understanding etcd

Anda dapat melihat bahawa keseluruhan proses adalah gelung. Di sini, kami akan menggariskan fungsi umum kaedah ini dan dalam analisis aliran tulis seterusnya, kami akan menyelidiki cara kaedah ini beroperasi pada medan teras raftLog dan tidak stabil.

  • HasReady: Seperti namanya, ia menyemak sama ada terdapat struct Ready yang perlu dihantar kepada pengguna. Contohnya, jika terdapat entri log yang tidak berterusan dalam tidak stabil yang tidak sedang dalam proses untuk diteruskan, HasReady akan kembali benar.
  • readyWithoutAccept: Dipanggil selepas HasReady kembali benar, kaedah ini mencipta struct Ready untuk dikembalikan kepada pengguna, termasuk entri log yang perlu diteruskan dan yang ditandakan sebagai komited.
  • acceptReady: Dipanggil selepas etcd raft melepasi struct Ready yang dicipta oleh readyWithoutAccept kepada pengguna. Ia menandakan masukan log dikembalikan dalam Sedia seperti dalam proses diteruskan dan digunakan, dan mencipta "panggilan balik" untuk dipanggil apabila pengguna memanggil Node.Advance, menandakan entri log sebagai berterusan dan digunakan.
  • Advance: Laksanakan "panggilan balik" yang dibuat dalam acceptReady selepas pengguna memanggil Node.Advance.

Cara Mentakrifkan Komited dan Gunaan

Terdapat dua perkara penting untuk dipertimbangkan di sini:

1. Kekal ≠ Komited

Seperti yang ditakrifkan pada mulanya, kemasukan log dianggap komited hanya apabila ia telah diteruskan oleh majoriti nod dalam kelompok Raft. Jadi, walaupun kami meneruskan Penyertaan yang dikembalikan oleh rakit etcd melalui Sedia, penyertaan ini belum lagi boleh ditanda sebagai komited.

Namun, apabila kami memanggil kaedah Advance untuk memaklumkan etcd raft bahawa kami telah menyelesaikan langkah kegigihan, etcd raft akan menilai status kegigihan merentas nod lain dalam kelompok dan menandakan beberapa entri log sebagai komited. Entri ini kemudiannya diberikan kepada kami melalui medan CommittedEntries pada struct Ready supaya kami boleh menggunakannya pada mesin keadaan.

Oleh itu, apabila menggunakan rakit etcd, masa untuk menandakan penyertaan sebagai komited diuruskan secara dalaman, dan pengguna hanya perlu memenuhi prasyarat kegigihan.

Secara dalaman, komitmen dicapai dengan memanggil kaedah raftLog.commitTo, yang mengemas kini raftLog.committed, sepadan dengan commitIndex dalam kertas Raft.

2. Komited ≠ Memohon

Selepas kaedah raftLog.commitTo dipanggil dalam etcd raft, entri log sehingga indeks raft.committed dianggap komited. Walau bagaimanapun, entri dengan indeks dalam julat lastApplied < index <= committedIndex belum lagi digunakan pada mesin keadaan. etcd raft akan mengembalikan entri komited tetapi tidak digunakan ini dalam medan CommittedEntries of Ready, membolehkan kami menggunakannya pada mesin keadaan. Sebaik sahaja kami memanggil Advance, etcd raft akan menandakan penyertaan ini sebagai digunakan.

Masa untuk menandakan entri seperti yang digunakan juga dikendalikan secara dalaman dalam rakit etcd; pengguna hanya perlu menggunakan penyertaan komited daripada Sedia ke mesin keadaan.

Satu lagi perkara halus ialah, dalam Raft, hanya Pemimpin boleh melakukan entri, tetapi semua nod boleh menggunakannya.

Aliran Pemprosesan Permintaan Tulis

Di sini, kami akan menyambungkan semua konsep yang dibincangkan sebelum ini dengan menganalisis aliran rakit etcd semasa ia mengendalikan permintaan tulis.

Keadaan Awal

Untuk membincangkan senario yang lebih umum, kami akan mulakan dengan Log Rakit yang telah pun melakukan dan menggunakan tiga entri log.

Understanding etcd

Dalam ilustrasi, hijau mewakili medan raftLog dan entri log yang disimpan dalam Storan, manakala merah mewakili medan tidak stabil dan entri log tidak kekal disimpan dalam entri.

Memandangkan kami telah melakukan dan menggunakan tiga entri log, kedua-duanya komited dan memohon ditetapkan kepada 3. Medan memohon memegang indeks entri log tertinggi daripada aplikasi sebelumnya, yang juga 3 dalam kes ini.

Pada ketika ini, tiada permintaan telah dimulakan, jadi tidak stabil.entri kosong. Indeks log seterusnya dalam Log Rakit ialah 4, menjadikan offset 4. Memandangkan tiada log sedang diteruskan, offsetInProgress juga ditetapkan kepada 4.

Keluarkan Permintaan

Sekarang, kami memulakan permintaan untuk menambahkan dua entri log pada Log Rakit.

Understanding etcd

Seperti yang ditunjukkan dalam ilustrasi, entri log yang dilampirkan disimpan dalam entri tidak stabil. Pada peringkat ini, tiada perubahan dibuat pada nilai indeks yang direkodkan dalam medan teras.

HasReady

Ingat kaedah HasReady? HasReady menyemak sama ada terdapat entri log yang tidak berterusan dan, jika ya, mengembalikan benar.

Logik untuk menentukan kehadiran entri log tidak berterusan adalah berdasarkan sama ada panjang unstable.entry[offsetInProgress-offset:] adalah lebih besar daripada 0. Jelas sekali, dalam kes kami:

type raftLog struct {
    storage Storage
    unstable unstable
    committed uint64
    applying uint64
    applied uint64
}

menunjukkan bahawa terdapat dua entri log yang tidak berterusan, jadi HasReady kembali benar.

Understanding etcd

sediaTanpa Terima

Tujuan readyWithoutAccept adalah untuk mencipta struct Ready untuk dikembalikan kepada pengguna. Memandangkan kami mempunyai dua entri log yang tidak berterusan, readyWithoutAccept akan memasukkan dua entri log ini dalam medan Entri bagi Ready yang dikembalikan.

Understanding etcd

terimaSedia

acceptReady dipanggil selepas struct Ready diserahkan kepada pengguna.

Understanding etcd

acceptReady mengemas kini indeks entri log yang sedang dalam proses dikekalkan kepada 6, bermakna entri log dalam julat [4, 6) kini ditandakan sebagai berterusan.

terlebih dahulu

Selepas pengguna meneruskan Entri dalam Sedia, mereka memanggil Node.Advance untuk memberitahu rakit etcd. Kemudian, etcd raft boleh melaksanakan "panggilan balik" yang dibuat dalam acceptReady.

Understanding etcd

"Panggil balik" ini mengosongkan entri log yang telah berterusan dalam unstable.enries, kemudian set offset kepada Storage.LastIndex 1, iaitu 6.

Komit Entri Log

Kami menganggap bahawa kedua-dua entri log ini telah dikekalkan oleh majoriti nod dalam gugusan Raft, jadi kami boleh menandakan kedua-dua entri log ini sebagai komited.

Understanding etcd

HasReady

Melanjutkan dengan gelung kami, HasReady mengesan kehadiran entri log yang dilakukan tetapi belum digunakan, jadi ia kembali benar.

Understanding etcd

sediaTanpa Terima

readyWithoutAccept mengembalikan entri log Sedia yang mengandungi (4, 5) yang dilakukan tetapi belum digunakan pada mesin keadaan.

Penyertaan ini dikira sebagai rendah, tinggi := menggunakan 1, komited 1, dalam selang kiri-buka, kanan-tutup.

Understanding etcd

terimaSedia

acceptReady kemudian tandakan entri log [4, 5] dikembalikan dalam Ready sebagai digunakan pada mesin keadaan.

Understanding etcd

terlebih dahulu

Selepas pengguna memanggil Node.Advance, etcd raft melaksanakan "panggilan balik" dan kemas kini digunakan pada 5, menunjukkan bahawa entri log pada indeks 5 dan lebih awal semuanya telah digunakan pada mesin keadaan.

Understanding etcd

Keadaan Akhir

Ini melengkapkan aliran pemprosesan untuk permintaan tulis. Keadaan akhir adalah seperti yang ditunjukkan di bawah, yang boleh dibandingkan dengan keadaan awal.

Understanding etcd

Ringkasan

Kami bermula dengan gambaran keseluruhan Raft Log, memperoleh pemahaman tentang konsep asasnya, diikuti dengan pandangan awal pada pelaksanaan rakit etcd. Kami kemudiannya mendalami modul teras Raft Log dalam etcd raft dan mempertimbangkan soalan penting. Akhirnya, kami mengikat semuanya bersama-sama melalui analisis lengkap aliran permintaan tulis.

Saya harap pendekatan ini membantu anda memperoleh pemahaman yang jelas tentang pelaksanaan rakit dll dan mengembangkan pandangan anda sendiri tentang Log Rakit.

Itu menyimpulkan artikel ini. Jika terdapat sebarang kesilapan atau pertanyaan, sila hubungi melalui mesej peribadi atau tinggalkan komen.

BTW, raft-foiver ialah versi ringkas rakit etcd yang saya laksanakan, mengekalkan semua logik teras Raft dan dioptimumkan mengikut proses dalam kertas Raft. Saya akan mengeluarkan siaran berasingan yang memperkenalkan perpustakaan ini pada masa hadapan. Jika anda berminat, sila hubungi Star, Fork atau PR!

Rujukan

  • https://github.com/B1NARY-GR0UP/raft
  • https://github.com/etcd-io/raft

Atas ialah kandungan terperinci Memahami Pelaksanaan Rakit etcd: Penyelaman Mendalam ke Log Rakit. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn