Primary hanya satu, tetapi anggota replica set yang menyimpan data ada beberapa — lalu ke mana sebaiknya aplikasi membaca? Pertanyaan itu dijawab oleh read preference: aturan di sisi driver yang menentukan anggota mana yang dipilih untuk melayani setiap operasi baca. Pilihan ini selalu merupakan tawar-menawar antara kesegaran data dan distribusi beban. Chapter ini memetakan lima mode read preference, mengujinya di mongosh, lalu memperkenalkan dua penyaring lanjutan: tag sets dan maxStalenessSeconds.
Lima Mode Read Preference #
| Mode | Perilaku | Kapan dipakai |
|---|---|---|
primary | Selalu ke primary (default) | Butuh data terbaru; write-then-read |
primaryPreferred | Ke primary; fallback ke secondary | Konsisten tapi tetap bisa baca saat failover |
secondary | Selalu ke secondary | Menyeret beban baca dari primary |
secondaryPreferred | Ke secondary; fallback ke primary | Seperti secondary, tetapi tahan saat secondary penuh |
nearest | Anggota berlatensi terendah, primary maupun secondary | Latensi minimum lebih penting daripada kesegaran |
Dua mode yang layak digarisbawahi: primaryPreferred menjaga baca tetap jalan ketika cluster sedang tanpa primary (failover), sementara secondaryPreferred adalah pilihan umum untuk beban analitik agar jalur tulis tidak terganggu.
Konsistensi yang Ditukar #
Secondary menyalin oplog secara asinkron — selalu ada selang waktu antara write di primary dan penerapan di secondary. Baca dari secondary karenanya menawarkan eventual consistency: hasil baca mungkin belum memuat write terbaru. Tiga pola akses yang paling terdampak:
- Baca-setelah-tulis: pengguna menyimpan ulasan, lalu membuka daftar ulasan — baca ke secondary bisa saja tidak menampilkan ulasannya sendiri.
- Agregat berat: laporan harian yang berjalan beberapa menit di secondary tidak masalah tertinggal beberapa detik.
- Baca lintas pengguna: pengguna A menulis, pengguna B membaca — keterlambatan hampir tak terasa.
Aturan praktisnya: data yang dibaca segera setelah ditulis pengguna yang sama sebaiknya dibaca dari primary; data historis dan analitik cocok diarahkan ke secondary. Saat butuh jaminan lebih ketat tanpa meninggalkan secondary, penyaring maxStalenessSeconds (di bagian akhir) membatasi seberapa tertinggal anggota yang boleh dipilih.
Mengatur Read Preference di mongosh #
Kita siapkan data pesanan dulu, lalu membaca seperti biasa — tanpa pengaturan apa pun:
use latihan_replika
db.dropDatabase()
db.pesanan.insertMany([
{ kode: "PSN-001", pelanggan: "Budi", buku: "Laut Bercerita", jumlah: 2 },
{ kode: "PSN-002", pelanggan: "Siti", buku: "Bumi Mantra", jumlah: 1 },
{ kode: "PSN-003", pelanggan: "Dewi", buku: "Rumah Kaca", jumlah: 3 }
])
db.pesanan.find({}, { _id: 0, kode: 1, pelanggan: 1 }).sort({ kode: 1 })Output yang Dihasilkan:
switched to db latihan_replika
{ ok: 1, dropped: 'latihan_replika' }
{
acknowledged: true,
insertedIds: {
'0': ObjectId('6ad3d5fdd47b1dab5c73e15e'),
'1': ObjectId('6ad3d5fdd47b1dab5c73e15f'),
'2': ObjectId('6ad3d5fdd47b1dab5c73e160')
}
}
[
{ kode: 'PSN-001', pelanggan: 'Budi' },
{ kode: 'PSN-002', pelanggan: 'Siti' },
{ kode: 'PSN-003', pelanggan: 'Dewi' }
]Query di atas berjalan dengan mode default primary. Sekarang kita alihkan read preference seluruh koneksi ke secondaryPreferred lalu membaca ulang:
db.getMongo().setReadPref("secondaryPreferred")
db.pesanan.find({}, { _id: 0, kode: 1, pelanggan: 1 }).sort({ kode: 1 })Output yang Dihasilkan:
[
{ kode: 'PSN-001', pelanggan: 'Budi' },
{ kode: 'PSN-002', pelanggan: 'Siti' },
{ kode: 'PSN-003', pelanggan: 'Dewi' }
]db.getMongo().setReadPref() mengubah read preference untuk seluruh operasi pada koneksi mongosh ini. Hasilnya identik — dan di sinilah kejujuran soal lingkungan latihan perlu dijelaskan:
- Di
rs0: koneksi kita memakaidirectConnection=true, sehingga driver menempel pada satu host untuk semua operasi dan tidak memilih server — perintah diterima apa adanya oleh satu-satunya anggota. - Di cluster nyata: mode
secondaryPreferredmembuat driver memilih secondary untuk setiap baca; ketika tidak ada secondary yang sehat, driver fallback ke primary — itulah makna “preferred” pada namanya. Modesecondarytanpa fallback akan menunggu hingga batas waktu pemilihan server.
Untuk satu query tertentu tanpa mengubah seluruh koneksi, read preference bisa diberikan langsung pada cursor:
db.pesanan.find({}, { _id: 0, kode: 1, jumlah: 1 }).sort({ kode: 1 }).readPref("nearest")Output yang Dihasilkan:
[
{ kode: 'PSN-001', jumlah: 2 },
{ kode: 'PSN-002', jumlah: 1 },
{ kode: 'PSN-003', jumlah: 3 }
]Metode cursor.readPref(mode) menimpa preferensi koneksi hanya untuk cursor itu — bentuk API yang juga tersedia di driver: PyMongo menyebutnya with_options(read_preference=...), Node.js withReadPreference(...). Pola tiga lapis ini berlaku umum: connection string mengatur default, setReadPref mengubah sesi/koneksi, dan opsi per-operasi paling spesifik menang.
Read Preference di Connection String #
Aplikasi produksi paling sering menyetel read preference lewat connection string — berlaku sejak koneksi pertama dibuat:
mongodb://mongod-1:27017,mongod-2:27017,mongod-3:27017/?replicaSet=rs0&readPreference=secondaryPreferredParameter readPreference menerima kelima mode yang sama. Penyaring lanjutan menempel sebagai parameter tambahan pada URI yang sama dan dibahas berikutnya.
Tag Sets dan maxStalenessSeconds #
Dua penyaring mempersempit kandidat anggota sebelum mode diterapkan:
- Tag sets: setiap anggota di
rs.conf()memiliki fieldtags— label bebas seperti{ dc: "jakarta", role: "analitik" }. Connection string kemudian memintareadPreferenceTags=dc:jakarta, sehingga hanya anggota berlabel itu yang dipilih. Ini cara resmi mengarahkan baca ke rakitan per-region atau ke anggota hidden khusus pelaporan. maxStalenessSeconds: batas tertinggal yang boleh diterima klien — misalmaxStalenessSeconds=90menolak secondary yang tertinggal lebih dari 90 detik dari primary. Driver menghitung estimasi tertinggal dari metadata heartbeat; bila semua secondary melebihi batas, pembacaan jatuh ke primary. Nilai minimum yang diizinkan adalah 90 detik.
Keduanya menjawab keluhan klasik pemakai secondary: “bagaimana saya tahu secondary ini tidak tertinggal parah?” — jawabannya adalah membuat driver yang menolak secondary basi, bukan menebak-nebak.
Rangkuman #
- Lima mode read preference:
primary(default),primaryPreferred,secondary,secondaryPreferred,nearest— masing-masing menukar kesegaran data dengan distribusi beban. - Baca dari secondary bersifat eventual consistent; baca-setelah-tulis oleh pengguna yang sama sebaiknya tetap ke primary.
- Read preference dapat diatur pada connection string, per koneksi lewat
setReadPref(), atau per cursor lewatreadPref()— yang paling spesifik menang. maxStalenessSeconds(minimum 90) dan tag sets mempersempit kandidat anggota: berlatensi wajar dan berlabel sesuai.
Baca sudah terarah; giliran tulisan yang diberi jaminan. Chapter Write Concern mengatur berapa anggota yang harus mengakui sebuah write sebelum aplikasi melanjutkan.