Image description
postgres create replication slot
Slot Replikasi Failover dengan Postgres 17

Slot Replikasi Failover dengan Postgres 17

Replika baca Postgres biasanya digunakan tidak hanya untuk mendistribusikan beban kueri di antara beberapa node, tetapi juga untuk memastikan ketersediaan tinggi (HA) basis data. Jika node utama (primer) dari sebuah cluster Postgres gagal, replika baca dapat ditingkatkan menjadi primer baru, yang kemudian memproses permintaan tulis (dan baca).

Sebelum Postgres versi 16, replika baca (atau server siaga) tidak dapat digunakan sama sekali untuk replikasi logis. Replikasi logis adalah metode untuk mereplikasi data dari publisher Postgres ke subscriber. Subscriber ini dapat berupa instance Postgres lain, serta alat non-Postgres, seperti CDC connector, yang menggunakan replikasi logis untuk change data capture (CDC). Slot replikasi logis—yang melacak sejauh mana subscriber tertentu telah mengonsumsi aliran perubahan basis data—hanya dapat dibuat di node utama cluster Postgres. Ini berarti setelah failover dari primer ke replika, Anda harus membuat slot replikasi baru dan biasanya juga memulai dengan snapshot awal data baru. Jika tidak, Anda mungkin kehilangan peristiwa perubahan yang terjadi setelah membaca dari slot di primer lama dan sebelum membuat slot di primer baru.

Meskipun alat eksternal seperti pg_failover_slots telah ditambahkan seiring waktu, solusi bawaan untuk melakukan failover slot replikasi dari satu node Postgres ke node lain sangat dirindukan oleh banyak pengguna. Situasi ini meningkat secara substansial dengan rilis Postgres 16, yang membawa dukungan untuk menyiapkan slot replikasi di replika baca. Fitur ini telah dibahas secara mendetail dalam artikel sebelumnya. Saat itu, juga dieksplorasi cara menggunakan slot replikasi di replika untuk mengimplementasikan failover slot replikasi secara manual. Namun kabar baiknya, mulai Postgres versi 17, semua ini tidak diperlukan lagi, karena akhirnya mendukung failover slot secara langsung!

Failover slot adalah slot replikasi yang dibuat di node utama dan secara otomatis disebarkan ke replika baca. Status mereka di replika tetap sinkron dengan slot upstream di primer, yang berarti setelah failover, saat meningkatkan replika menjadi primer, Anda dapat terus mengonsumsi slot di primer baru tanpa risiko kehilangan peristiwa perubahan. Ini merupakan kabar baik untuk menggunakan alat seperti CDC connector (dan dengan perluasan, platform data yang menyediakan konektor CDC Postgres terkelola) dalam skenario HA, jadi mari kita lihat lebih dekat cara kerjanya.

Halo, Failover Slot!

Mari kita mulai dengan menjelajahi failover slot hanya dari perspektif penggunaan antarmuka SQL Postgres untuk replikasi logis. Jika Anda ingin mengikuti, periksa proyek contoh yang berisi file Docker Compose yang menyiapkan Postgres primer dan replika baca (berdasarkan pengaturan yang memudahkan memulai cluster Postgres sementara untuk tujuan pengujian), serta beberapa komponen lain yang akan digunakan nanti. Jalankan semuanya dengan perintah:

$ docker compose up

Primer dan replika disinkronkan melalui slot replikasi fisik (yaitu, tidak seperti replikasi logis, semua segmen WAL direplikasi), memastikan bahwa semua perubahan data yang dilakukan di primer langsung direplikasi ke replika. Dapatkan sesi di primer (saya akan menggunakan pgcli, klien CLI Postgres favorit, tetapi psql juga bisa):

$ pgcli --prompt "\u@primary:\d> " "postgresql://user:top-secret@localhost:5432/inventorydb"

Prompt telah disesuaikan untuk menunjukkan instance saat ini. Untuk memverifikasi Anda berada di primer dan bukan replika, jalankan perintah berikut:

SELECT * from pg_is_in_recovery();

Hasilnya False.

Primer dan replika sudah dikonfigurasi dengan wal_level logical, seperti yang diperlukan untuk replikasi logis:

SHOW wal_level;

Hasilnya logical.

Catatan: Jika Anda menjalankan Postgres di layanan basis data awan (di mana versi 17 tersedia), Anda perlu mengatur parameter rdsl_replication ke on.

Ada slot replikasi fisik untuk menyinkronkan perubahan dari primer ke server replika:

SELECT slot_name, slot_type, active, plugin, database, failover, synced, confirmed_flush_lsn FROM pg_replication_slots;

Slot ini harus ditambahkan ke set slot siaga yang disinkronkan menggunakan opsi konfigurasi synchronized_standby_slots:

ALTER SYSTEM SET synchronized_standby_slots='replication_slot';
SELECT pg_reload_conf();

Pengaturan ini, baru di Postgres 17, memastikan bahwa slot replikasi logis yang akan kita buat tidak dapat maju melampaui nomor urut log (LSN) yang dikonfirmasi dari slot fisik ini. Tanpa pengaturan itu, konsumen replikasi logis seperti CDC connector mungkin menerima perubahan yang tidak pernah disebarkan ke replika jika terjadi kegagalan primer, menghasilkan keadaan yang tidak konsisten.

Selanjutnya, dapatkan sesi basis data di replika:

$ pgcli --prompt "\u@replica:\d> " "postgresql://user:top-secret@localhost:5433/inventorydb"

Verifikasi Anda berada di node yang benar:

SELECT * from pg_is_in_recovery();

Hasilnya True.

Replika sudah dikonfigurasi dengan hot_standby_feedback=ON yang merupakan persyaratan agar failover slot berfungsi. Selain itu, nama basis data harus ditambahkan ke primary_conninfo di replika (string koneksi untuk terhubung ke primer). Saya tidak dapat menemukan cara untuk hanya menambahkan satu atribut, jadi saya mengambil nilai saat ini dan menambahkan nama basis data, sehingga string lengkap dapat ditulis kembali (di RDS, pengaturan itu tidak dapat diubah, sebagai gantinya atur parameter rdsl_slot_sync_dbname ke nama basis data):

ALTER SYSTEM SET primary_conninfo = '... dbname=inventorydb';
SELECT pg_reload_conf();

Pada titik ini, primer dan replika sudah siap agar failover slot berfungsi. Jadi, mari kita buat slot replikasi logis di primer selanjutnya:

SELECT * FROM pg_create_logical_replication_slot('test_slot', 'test_decoding', false, false, true);

Sejak Postgres 17, ada parameter opsional baru dari fungsi pg_create_logical_replication_slot() untuk menentukan bahwa failover slot harus dibuat (failover=true). Di replika, panggil pg_sync_replication_slots() untuk menyinkronkan semua failover slot dari primer:

SELECT pg_sync_replication_slots();

Ini akan memastikan bahwa slot di primer dan replika berada di LSN yang sama persis. Untuk memverifikasi, kueri status slot di kedua node menggunakan kueri yang sama dengan di atas. Saat ini, confirmed_flush_lsn dari slot di replika cocok dengan slot di primer, yaitu kedua slot sinkron. Namun begitu klien mengonsumsi perubahan dari slot primer, slot di replika tidak akan diperbarui sesuai. Anda dapat secara manual memanggil pg_sync_replication_slots() berulang kali untuk menyinkronkan slot di replika, tetapi untungnya ada cara yang lebih mudah. Dengan mengatur sync_replication_slots ke on di replika, pekerja sinkronisasi akan dimulai, yang akan menyebarkan status replikasi secara otomatis:

ALTER SYSTEM SET sync_replication_slots = true;
SELECT pg_reload_conf();

Sekarang lakukan beberapa perubahan data di primer dan konsumsi dari slot replikasi:

UPDATE inventoryers SET first_name='Sarah' where id = 1001;
UPDATE inventoryers SET first_name='Sam' where id = 1001;
SELECT * FROM pg_logical_slot_get_changes('test_slot', NULL, NULL);

Jika Anda kueri pg_replication_slots sekali lagi, Anda akan melihat bahwa confirmed flush LSN dari slot di replika masih cocok dengan yang di primer. Untuk menyimpulkan eksperimen dasar, mari kita lihat apa yang terjadi ketika kita mencoba mengonsumsi slot replikasi di server replika:

SELECT * FROM pg_logical_slot_get_changes('test_slot', NULL, NULL);
-- error: cannot use replication slot for logical decoding

Ini memicu kesalahan: karena status failover slot di replika didorong oleh slot yang sesuai di primer, mereka tidak dapat dikonsumsi. Hanya setelah meningkatkan replika menjadi primer, klien dapat terhubung ke slot itu dan membaca peristiwa perubahan darinya. Mari kita coba dengan menyiapkan instance konektor CDC Postgres selanjutnya!

Failover Slot dalam Platform Data

Platform data adalah platform data waktu-nyata terkelola penuh berdasarkan Apache Flink. Platform ini menawarkan konektor terkelola untuk berbagai sistem sumber dan tujuan, memungkinkan Anda membangun pipa ETL yang kuat dan efisien dengan mudah. Konektor CDC Postgresnya menggunakan CDC connector di bawah kap, yang pada gilirannya menggunakan replikasi logis untuk mengambil peristiwa perubahan data dari Postgres. Berkat failover slot, dimungkinkan untuk terus mengalirkan perubahan dari replika baca Postgres yang ditingkatkan menjadi primer ke platform data, tanpa kehilangan peristiwa apa pun.

Untuk kasus penggunaan semacam ini, masuk akal untuk menempatkan proksi basis data di depan cluster basis data, mengekspos satu titik akhir yang stabil untuknya. Ini akan memungkinkan kita nantinya untuk melakukan failover dari primer ke replika tanpa harus mengonfigurasi ulang konektor Postgres di platform data. Dalam skenario produksi, pendekatan ini akan membuat fail-over menjadi detail implementasi yang dikelola oleh tim yang memiliki basis data, tidak memerlukan koordinasi dengan tim yang menjalankan platform data. Pengaturan Docker Compose di atas berisi proksi connection pooler untuk tujuan ini.

Untuk mengakses basis data di mesin Anda dari platform data yang berjalan di cloud, kita akan menggunakan layanan terowongan API gateway, yang memungkinkan Anda mengekspos sumber daya non-publik ke cloud, yaitu persis apa yang kita butuhkan untuk contoh ini. Anda dapat mempertimbangkan pendekatan ini juga untuk terhubung ke basis data on-prem dalam kasus penggunaan produksi.

Arsitektur keseluruhannya terlihat seperti ini:

Gbr. 1: Gambaran solusi

Untuk langkah-langkah berikut, Anda perlu memiliki hal-hal ini:

  • Akun platform data gratis
  • CLI platform data terinstal di mesin Anda
  • Akun layanan terowongan gratis

Proksi connection pooler dikonfigurasi untuk terhubung ke host Postgres primer, dan layanan terowongan mengekspos terowongan yang dapat diakses publik untuk terhubung ke connection pooler.

Platform data menyediakan dukungan untuk mendeklarasikan sumber daya Anda—konektor, pipa SQL, dll.—secara deklaratif. Anda menjelaskan sumber daya yang ingin Anda miliki dalam file YAML, dan platform data akan mengurus materialisasinya di akun Anda. Proyek contoh berisi definisi untuk konektor sumber CDC Postgres, rahasia dengan kata sandi basis data yang akan digunakan oleh konektor, dan stream, yang akan ditulis oleh konektor datanya.

Layanan terowongan membuat terowongan untuk mengekspos instance Postgres lokal secara publik menggunakan nama host dan port acak. Dengan bantuan httpie dan jq, kita dapat mengambil titik akhir publik dari terowongan dari API REST lokal layanan terowongan (alternatifnya, ada juga UI yang berjalan di localhost:4040), memungkinkan kita menyebarkan nilai-nilai ini ke definisi sumber daya melalui sed sebelum menerapkannya menggunakan CLI platform data (nama file spesial - menunjukkan untuk membaca dari stdin daripada dari file yang diberikan).

Pada titik ini, semua sumber daya telah dibuat di akun platform data Anda, tetapi konektor sumber Postgres belum berjalan. Sebelum kita dapat memulainya (“mengaktifkan” dalam terminologi platform data), kita perlu membuat slot replikasi di basis data, mengonfigurasinya sebagai failover slot. Agar konektor CDC Postgres dapat mengambil slot, slot harus memiliki nama decodable_<connection-id>. Untuk mendapatkan id koneksi, lihat output dari perintah decodable apply di atas, atau ambil menggunakan decodable query.

Di instance Postgres primer, buat slot replikasi, konfigurasikan sebagai failover slot:

SELECT * FROM pg_create_logical_replication_slot('decodable_<connection-id>', 'pgoutput', false, false, true);

Selanjutnya, aktifkan konektor:

$ decodable connection activate <connection-id>

Setelah aktivasi pertama, konektor akan membuat snapshot awal data di tabel pelanggan dan kemudian membaca setiap perubahan data berikutnya secara inkremental melalui slot replikasi yang telah kita buat. Untuk melihat data, buka antarmuka web platform data di browser Anda dan buka tampilan “Streams”. Pilih stream inventorydb__inventory__customers dan buka tab “Preview” di mana Anda akan melihat data dari snapshot. Lakukan beberapa perubahan data di sesi Postgres di node primer, misalnya perbarui nama depan. Tak lama kemudian, pembaruan ini akan tercermin dalam pratinjau stream juga.

Sekarang mari kita simulasikan failover dari primer ke server replika dan lihat bagaimana failover slot replikasi ditangani. Hentikan node Postgres primer:

$ docker compose stop postgres_primary

Di sesi basis data di replika, tingkatkan replika menjadi primer:

select pg_promote();

Pada titik ini, connection pooler masih menunjuk ke server primer sebelumnya yang sekarang sudah mati. Ubah konfigurasinya di file Docker Compose sehingga mengarah ke primer baru:

pgbouncer:
...
environment:
- DB_HOST=postgres_replica
...

Hentikan dan mulai ulang connection pooler (proksi lain juga dapat memuat ulang konfigurasi yang diperbarui dengan cepat). Jika Anda kembali ke antarmuka web platform data dan melihat koneksi inventorydb_source, seharusnya dalam status “Retrying” saat ini, karena koneksi ke primer sebelumnya terputus (melalui proksi). Setelah beberapa saat, akan kembali ke status “Running”, karena proksi sekarang merutekan ke server primer baru. Konektor sekarang mengonsumsi dari slot replikasi di server primer baru itu, seperti yang Anda konfirmasi dengan melakukan beberapa perubahan data lagi di node itu dan memeriksa data di pratinjau stream platform data, juga dengan memverifikasi bahwa slot replikasi sekarang dalam status Active.

INSERT INTO inventoryers VALUES (default, 'Rudy', 'Replica', 'rudy@example', FALSE);

Jika Anda mengambil status slot replikasi lagi menggunakan kueri yang sama seperti di atas, Anda akan melihat bahwa slot ditandai sebagai aktif sekarang.

Kesimpulan

Failover slot adalah bagian penting dari penggunaan Postgres dan replikasi logis dalam skenario HA. Ditambahkan di Postgres 17, mereka memungkinkan klien replikasi logis seperti CDC connector untuk terus mengalirkan peristiwa perubahan setelah failover basis data, memastikan tidak ada peristiwa yang hilang dalam proses. Ini membuat solusi sebelumnya seperti menyinkronkan slot secara manual di server siaga (seperti yang didukung sejak Postgres 16) atau alat eksternal seperti pg_failover_slots menjadi usang (meskipun yang terakhir masih berguna jika Anda menggunakan versi Postgres yang lebih lama dan belum dapat meningkatkan ke 17).

Untuk membuat failover slot, parameter failover baru harus diatur ke true saat memanggil pg_create_logical_replication_slot(). Saat ini, CDC connector belum melakukan ini, tetapi direncanakan untuk mengimplementasikan perubahan yang diperlukan dalam waktu dekat. Pantau terus perkembangannya. Sementara itu, Anda dapat membuat slot replikasi secara manual seperti yang dijelaskan di atas. Untuk mempelajari lebih lanjut tentang failover slot Postgres, lihat posting blog oleh Bertrand Drouvot dan Amit Kapila. Pengguna layanan basis data awan harus merujuk pada dokumentasi resmi tentang mengelola failover slot.

© 2026 - Semua hak dilindungi undang-undang. PT dengan modal Rp 10.000.000.000. Jl. Jend. Sudirman Kav. 52-53, Jakarta Selatan 12190