Pengenalan replica set

Memahami redundansi data, pemilihan primary, dan failover pada replica set.

Daftar isi

Replica set adalah sekelompok proses mongod yang menyimpan data yang sama dan saling menjaga ketersediaannya. Operasi tulis diterima oleh satu anggota bernama primary, lalu disalin ke anggota lain bernama secondary melalui oplog, yaitu log operasi milik replica set. Topik ini membahas redundansi data yang ditawarkan replica set, pembacaan konfigurasi dan status topologi melalui rs.conf(), rs.status(), dan db.hello(), serta mekanisme pemilihan primary ketika anggota utama berhenti. Server latihan pada jalur ini sudah berjalan sebagai replica set satu node bernama rs0, sehingga seluruh perintah topologinya dapat dijalankan langsung.

Konsep replica set dan redundansi data#

Replica set membagi peran anggotanya menjadi dua. Anggota primary menerima seluruh operasi tulis. Anggota secondary mengikuti oplog milik primary dan menerapkan operasi yang sama secara berurutan, sehingga isi datanya selalu mengikuti primary dengan jeda yang biasanya singkat. Pembacaan secara bawaan diarahkan ke primary, sedangkan pengaturan read preference, yaitu aturan pemilihan anggota yang menerima pembacaan, dapat mengarahkan pembacaan ke secondary untuk kebutuhan tertentu.

Redundansi inilah tujuan utama replica set. Ketika satu anggota berhenti, anggota lain masih memuat salinan data dan layanan dapat berlanjut. Dengan demikian, kehilangan satu mesin tidak berarti kehilangan data atau layanan yang berhenti. Untuk latihan, satu node yang dijalankan sebagai replica set sudah cukup, karena seluruh mekanisme topologinya tetap berjalan. Replica set pada lingkungan produksi lazimnya memuat tiga anggota atau lebih yang saling menggantikan.

Konfigurasi replica set dengan rs.conf()#

Perintah rs.conf() mengembalikan dokumen konfigurasi replica set yang sedang diikuti shell. Field _id menuliskan nama replica set, version menuliskan nomor revisi konfigurasi yang bertambah setiap kali konfigurasi diubah, sedangkan members memuat daftar anggota beserta properti perannya seperti host, votes, dan priority. Perubahan konfigurasi dilakukan melalui rs.reconfig(), dan nomor version mencegah konfigurasi lama menimpa konfigurasi yang lebih baru.

mongosh
const conf = rs.conf()
conf._id
conf.version
conf.members.length
conf.members[0]
text Keluaran
rs0
1
1
{
  _id: 0,
  host: '127.0.0.1:27017',
  arbiterOnly: false,
  buildIndexes: true,
  hidden: false,
  priority: 1,
  tags: {},
  secondaryDelaySecs: Long('0'),
  votes: 1
}

Konfigurasi tersebut menegaskan bahwa server latihan adalah satu-satunya anggota rs0. Anggota tunggal itu berada di 127.0.0.1:27017 dengan satu suara (votes) dan prioritas 1. Kedua nilai tersebut adalah nilai bawaan yang membuat anggota ini setara dengan anggota lain apabila jumlah anggota ditambah. Properti hidden, arbiterOnly, dan secondaryDelaySecs mengatur varian anggota khusus yang tidak dipakai pada konfigurasi bawaan ini.

Identitas node dengan hello#

Perintah db.hello() menjawab pertanyaan paling mendasar tentang topologi, yaitu siapa node yang sedang dihubungi dan apa perannya. Perintah yang sama dipanggil secara berkala oleh driver saat koneksi dibuka, sehingga driver mengetahui anggota mana yang menerima tulis dan anggota mana yang menjadi cadangan baca. Field yang paling sering dibaca adalah setName, isWritablePrimary, me, dan hosts.

mongosh
const h = db.hello()
h.setName
h.isWritablePrimary
h.me
h.hosts
h.setVersion
text Keluaran
rs0
true
127.0.0.1:27017
[ '127.0.0.1:27017' ]
1

Keluaran tersebut menunjukkan bahwa node yang dihubungi tergabung dalam replica set rs0 dan saat ini berperan sebagai anggota yang menerima tulis. Field me menuliskan alamat yang dipakai node untuk memperkenalkan dirinya, sedangkan hosts memuat daftar seluruh anggota voting yang dikenal oleh replica set. Nilai isWritablePrimary berubah menjadi false ketika perintah yang sama dijalankan pada anggota secondary.

Status anggota dengan rs.status()#

Perintah rs.status() melaporkan keadaan anggota pada saat itu, berbeda dengan rs.conf() yang menampilkan konfigurasi yang diinginkan. Field set menuliskan nama replica set, myState menuliskan kode keadaan node yang dihubungi, sedangkan setiap elemen members memuat name, health, dan stateStr yang menuliskan peran anggotanya dalam teks.

mongosh
const st = rs.status()
st.set
st.myState
st.members.map(m => m.stateStr)
st.members.map(m => m.health)
st.members.map(m => m.name)
text Keluaran
rs0
1
[ 'PRIMARY' ]
[ 1 ]
[ '127.0.0.1:27017' ]

Elemen members pada replica set penuh akan memuat satu baris per anggota, sehingga sekali pandang terlihat anggota mana yang berperan PRIMARY dan anggota mana yang berperan SECONDARY. Nilai health berupa 1 menandakan anggota terjangkau, sedangkan 0 menandakan anggota yang tidak merespons. Dokumen lengkap rs.status() juga memuat uptime, tanggal, dan posisi oplog yang berubah setiap saat, sehingga contoh di atas menampilkan field yang stabil saja.

Pemilihan primary dan failover#

Ketika anggota primary tidak terjangkau oleh mayoritas anggota voting, anggota yang tersisa menjalankan pemilihan (election) untuk menetapkan primary baru. Anggota dengan priority tertinggi dan oplog yang paling mutakhir diutamakan. Pemilihan berlangsung cepat, sehingga jeda layanan biasanya hanya beberapa detik. Peristiwa perpindahan peran secara otomatis inilah yang disebut failover.

Selama tidak ada primary, seluruh operasi tulis ditolak dengan error NotWritablePrimary sampai primary baru terpilih. Mekanisme retryable writes membantu aplikasi menghadapi masa jeda tersebut dengan menulis ulang operasi yang belum terkonfirmasi ke primary baru. Server latihan ini memuat satu anggota saja, sehingga tidak ada pemilih lain dan peran primary tidak pernah berpindah. Jumlah anggota voting yang ganjil dipilih pada lingkungan nyata agar mayoritas tetap ada ketika satu anggota hilang.

Kesalahan umum#

Kesalahan pertama adalah mengirim tulisan ke anggota secondary. Anggota tersebut menolaknya dengan error NotWritablePrimary, dan error ini juga muncul pada masa transisi, yaitu setelah primary lama berhenti dan sebelum primary baru terpilih. Aplikasi yang benar mengarahkan tulisannya melalui driver yang mengikuti topologi, atau menunggu primary baru sebelum menulis ulang.

Kesalahan kedua adalah menganggap replica set satu node memberikan ketersediaan tambahan. Seluruh mekanisme topologi tetap berjalan, tetapi data dan layanan hilang ketika satu-satunya proses mongod berhenti, sehingga node tunggal seperti ini hanya layak untuk latihan. Perbaikannya adalah menambah anggota pada mesin terpisah, bukan sekadar menjalankan rs0 pada satu server.

Ringkasan#

  • Replica set mereplikasi tulisan dari primary ke secondary melalui oplog, sehingga data tersalin di lebih dari satu anggota.
  • rs.conf() menampilkan konfigurasi anggota, db.hello() menyatakan peran node yang dihubungi, dan rs.status() melaporkan keadaan anggota saat itu.
  • Pemilihan primary berlangsung otomatis ketika mayoritas anggota voting kehilangan primary-nya, dan masa jeda ini ditandai error NotWritablePrimary.
  • Jumlah anggota voting yang ganjil menjaga mayoritas tetap ada, sedangkan replica set satu node hanya cocok untuk latihan.

Referensi#