Apa itu Slot Replikasi?
Dulu saat "Slot Replikasi" belum diperkenalkan, mengelola segmen WAL adalah sebuah tantangan. Dalam replikasi streaming standar, master tidak memiliki pengetahuan tentang status budak. Ambil contoh master yang menjalankan transaksi besar, sementara node siaga dalam mode pemeliharaan selama beberapa jam (seperti meningkatkan paket sistem, menyesuaikan keamanan jaringan, meningkatkan perangkat keras, dll.). Pada titik tertentu, master menghapus log transaksinya (segmen WAL) saat pos pemeriksaan lewat. Setelah budak keluar dari pemeliharaan, mungkin ada jeda budak yang besar dan harus mengejar master. Pada akhirnya, budak tersebut akan mendapatkan masalah fatal seperti di bawah ini:
LOG: started streaming WAL from primary at 0/73000000 on timeline 1
FATAL: could not receive data from WAL stream: ERROR: requested WAL segment 000000010000000000000073 has already been removed
Pendekatan tipikal adalah dengan menetapkan di postgresql.conf Anda skrip arsip WAL yang akan menyalin file WAL ke satu atau lebih lokasi arsip jangka panjang. Jika Anda tidak memiliki standby atau klien replikasi streaming lainnya, maka pada dasarnya server dapat membuang file WAL setelah skrip arsip selesai atau merespons OK. Tetapi Anda masih memerlukan beberapa file WAL terbaru untuk pemulihan kerusakan (data dari file WAL terbaru diputar ulang selama pemulihan kerusakan. Dalam contoh kami tentang node siaga yang ditempatkan untuk periode pemeliharaan yang lama, masalah muncul saat kembali online dan meminta primer untuk file WAL yang tidak lagi dimiliki primer, maka replikasi gagal.
Masalah ini telah diatasi di PostgreSQL 9.4 melalui "Replication Slots".
Jika tidak menggunakan slot replikasi, cara umum untuk mengurangi risiko kegagalan replikasi adalah dengan menyetel wal_keep_segments cukup tinggi sehingga file WAL yang mungkin diperlukan tidak akan dirotasi atau didaur ulang. Kerugian dari pendekatan ini adalah sulit untuk menentukan nilai apa yang terbaik untuk pengaturan Anda. Anda tidak perlu perawatan setiap hari atau Anda tidak perlu menyimpan banyak file WAL yang memakan penyimpanan disk Anda. Meskipun ini berhasil, ini bukan solusi yang ideal karena mempertaruhkan ruang disk pada master dapat menyebabkan transaksi masuk gagal.
Pendekatan alternatif untuk tidak menggunakan slot replikasi adalah dengan mengonfigurasi PostgreSQL dengan pengarsipan berkelanjutan dan menyediakan restore_command untuk memberikan akses replika ke arsip. Untuk menghindari penumpukan WAL di primer, Anda dapat menggunakan volume atau perangkat penyimpanan terpisah untuk file WAL, misalnya, SAN atau NFS. Hal lain adalah dengan replikasi sinkron karena mengharuskan primer harus menunggu node siaga untuk melakukan transaksi. Ini berarti, ini memastikan bahwa file WAL telah diterapkan ke node siaga. Tapi tetap saja, yang terbaik adalah Anda memberikan perintah pengarsipan dari primer sehingga setelah WAL didaur ulang di primer, yakinlah bahwa Anda memiliki cadangan WAL untuk pemulihan. Meskipun dalam beberapa situasi, replikasi sinkron bukanlah solusi ideal karena dilengkapi dengan beberapa overhead kinerja dibandingkan dengan replikasi asinkron.
Jenis Slot Replikasi
Ada dua jenis slot replikasi. Ini adalah:
Slot Replikasi Fisik
Dapat digunakan untuk replikasi streaming standar. Mereka akan memastikan bahwa data tidak didaur ulang terlalu dini.
Slot Replikasi Logis
Replikasi logis melakukan hal yang sama seperti slot replikasi fisik dan digunakan untuk replikasi logis. Namun, mereka digunakan untuk decoding logis. Ide di balik decoding logis adalah untuk memberi pengguna kesempatan untuk melampirkan log transaksi dan mendekodekannya dengan sebuah plugin. Ini memungkinkan untuk mengekstrak perubahan yang dibuat ke database dan oleh karena itu ke log transaksi dalam format apa pun dan untuk tujuan apa pun.
Di blog ini, kita akan menggunakan slot replikasi fisik dan cara mencapainya menggunakan ClusterControl.
Keuntungan dan Kerugian Menggunakan Slot Replikasi
Slot replikasi pasti bermanfaat setelah diaktifkan. Secara default, "Slot Replikasi" tidak diaktifkan dan harus disetel secara manual. Di antara keuntungan menggunakan Slot Replikasi adalah
- Memastikan master mempertahankan segmen WAL yang cukup agar semua replika dapat menerimanya
- Mencegah master menghapus baris yang dapat menyebabkan konflik pemulihan pada replika
- Seorang master hanya dapat mendaur ulang log transaksi setelah digunakan oleh semua replika. Keuntungannya di sini adalah bahwa seorang budak tidak akan pernah ketinggalan sehingga diperlukan sinkronisasi ulang.
Slot replikasi juga dilengkapi dengan beberapa peringatan.
- Slot replikasi yatim piatu dapat menyebabkan pertumbuhan disk yang tidak terbatas karena tumpukan file WAL dari master
- Node slave yang ditempatkan dalam pemeliharaan yang lama (seperti hari atau minggu) dan yang terikat ke slot replikasi akan memiliki pertumbuhan disk yang tidak terbatas karena tumpukan file WAL dari master
Anda dapat memantau ini dengan menanyakan pg_replication_slots untuk menentukan slot yang tidak digunakan. Kami akan memeriksanya kembali nanti.
Menggunakan Slot Replikasi
Seperti yang dinyatakan sebelumnya, ada dua jenis slot replikasi. Untuk blog ini, kami akan menggunakan slot replikasi fisik untuk replikasi streaming.
Membuat Slot Replikasi
Membuat replikasi itu sederhana. Anda perlu memanggil fungsi yang ada pg_create_physical_replication_slot untuk melakukan ini dan harus dijalankan dan dibuat di master node. Fungsinya sederhana,
maximus_db=# \df pg_create_physical_replication_slot
Schema | pg_catalog
Name | pg_create_physical_replication_slot
Result data type | record
Argument data types | slot_name name, immediately_reserve boolean DEFAULT false, OUT slot_name name, OUT xlog_position pg_lsn
Type | normal
mis. Membuat slot replikasi bernama slot1,
postgres=# SELECT pg_create_physical_replication_slot('slot1');
-[ RECORD 1 ]-----------------------+---------
pg_create_physical_replication_slot | (slot1,)
Nama slot replikasi dan konfigurasi dasarnya hanya untuk seluruh sistem dan bukan untuk seluruh kluster. Misalnya, jika Anda memiliki nodeA (master saat ini), dan node standby nodeB dan nodeC, membuat slot pada master nodeA yaitu "slot1", maka data tidak akan tersedia untuk nodeB dan nodeC. Oleh karena itu, ketika failover/switchover akan terjadi, Anda perlu membuat kembali slot yang telah Anda buat.
Menjatuhkan Slot Replikasi
Slot replikasi yang tidak digunakan harus dibuang atau dihapus. Seperti yang dinyatakan sebelumnya, ketika ada slot atau slot replikasi yatim piatu yang belum ditetapkan ke klien atau node siaga mana pun, ini dapat menyebabkan masalah ruang disk tanpa batas jika dibiarkan tidak dilepas. Jadi sangat penting bahwa ini harus dijatuhkan ketika tidak lagi digunakan. Untuk menghapusnya, cukup panggil pg_drop_replication_slot. Fungsi ini memiliki definisi sebagai berikut:
maximus_db=# \df pg_drop_replication_slot
Schema | pg_catalog
Name | pg_drop_replication_slot
Result data type | void
Argument data types | name
Type | normal
Melepasnya sederhana:
maximus_db=# select pg_drop_replication_slot('slot2');
-[ RECORD 1 ]------------+-
pg_drop_replication_slot |
Memantau Slot Replikasi PostgreSQL Anda
Memantau slot replikasi Anda adalah sesuatu yang tidak ingin Anda lewatkan. Cukup kumpulkan informasi dari view pg_replication_slots di node utama/master seperti di bawah ini:
postgres=# select * from pg_replication_slots;
-[ RECORD 1 ]-------+-----------
slot_name | main_slot
plugin |
slot_type | physical
datoid |
database |
active | t
active_pid | 16297
xmin |
catalog_xmin |
restart_lsn | 2/F4000108
confirmed_flush_lsn |
-[ RECORD 2 ]-------+-----------
slot_name | main_slot2
plugin |
slot_type | physical
datoid |
database |
active | f
active_pid |
xmin |
catalog_xmin |
restart_lsn |
confirmed_flush_lsn |
Hasil di atas menunjukkan bahwa main_slot telah diambil, tetapi main_slot2 tidak.
Hal lain yang dapat Anda lakukan adalah memantau seberapa banyak lag di belakang slot yang Anda miliki. Untuk mencapai ini, Anda cukup menggunakan kueri berdasarkan hasil sampel di bawah ini:
postgres=# SELECT redo_lsn, slot_name,restart_lsn,
round((redo_lsn-restart_lsn) / 1024 / 1024 / 1024, 2) AS GB_behind
FROM pg_control_checkpoint(), pg_replication_slots;
redo_lsn | slot_name | restart_lsn | gb_behind
------------+-----------+-------------+-----------
1/8D400238 | slot1 | 0/9A000000 | 3.80
Tapi redo_lsn tidak ada di 9.6, harus menggunakan redo_location, jadi di 9.6,
imbd=# SELECT redo_location, slot_name,restart_lsn,
round((redo_location-restart_lsn) / 1024 / 1024 / 1024, 2) AS GB_behind
FROM pg_control_checkpoint(), pg_replication_slots;
-[ RECORD 1 ]-+-----------
redo_location | 2/F6008BE0
slot_name | main_slot
restart_lsn | 2/F6008CC0
gb_behind | 0.00
-[ RECORD 2 ]-+-----------
redo_location | 2/F6008BE0
slot_name | main_slot2
restart_lsn | 2/F6008CC0
gb_behind | 0.00
Persyaratan Variabel Sistem
Menerapkan slot replikasi memerlukan pengaturan manual. Ada variabel yang harus Anda ingat yang memerlukan perubahan dan ditentukan dalam postgresql.conf Anda. Lihat di bawah:
- max_replication_slots – Jika disetel ke 0, ini berarti slot replikasi dinonaktifkan sepenuhnya. Jika Anda menggunakan PostgreSQL <10 versi, slot ini harus ditentukan selain 0 (default). Sejak PostgreSQL 10, defaultnya adalah 10. Variabel ini menentukan jumlah maksimum slot replikasi. Menyetelnya ke nilai yang lebih rendah dari jumlah slot replikasi yang ada saat ini akan mencegah server memulai.
- wal_level – setidaknya harus replika atau lebih tinggi (replika adalah default). Menyetel hot_standby atau arsip akan dipetakan ke replika. Untuk slot replikasi fisik, replika sudah cukup. Untuk slot replikasi logis, logis lebih disukai.
- max_wal_senders – disetel ke 10 secara default, 0 dalam versi 9.6 yang berarti replikasi dinonaktifkan. Kami menyarankan Anda mengatur ini setidaknya ke 16 terutama saat menjalankan dengan ClusterControl.
- hot_standby – dalam versi <10, Anda perlu menyetel ini ke yang tidak aktif secara default. Ini penting untuk node siaga yang berarti saat aktif, Anda dapat menghubungkan dan menjalankan kueri selama pemulihan atau dalam mode siaga.
- primary_slot_name – variabel ini disetel melalui recovery.conf pada node standby. Ini adalah slot yang akan digunakan oleh penerima atau node siaga saat menghubungkan dengan pengirim (atau primer/master).
Anda harus memperhatikan bahwa sebagian besar variabel ini memerlukan restart layanan database untuk memuat ulang nilai baru.
Menggunakan Slot Replikasi di Lingkungan PostgreSQL ClusterControl
Sekarang, mari kita lihat bagaimana kita dapat menggunakan slot replikasi fisik dan mengimplementasikannya dalam pengaturan Postgres yang dikelola oleh ClusterControl.
Menerapkan Node Database PostgreSQL
Mari kita mulai menerapkan Cluster PostgreSQL 3-simpul menggunakan ClusterControl menggunakan versi PostgreSQL 9.6 kali ini.
ClusterControl akan menyebarkan node dengan variabel sistem berikut yang ditentukan berdasarkan defaultnya atau nilai yang disetel. Dalam:
postgres=# select name, setting from pg_settings where name in ('max_replication_slots', 'wal_level', 'max_wal_senders', 'hot_standby');
name | setting
-----------------------+---------
hot_standby | on
max_replication_slots | 0
max_wal_senders | 16
wal_level | replica
(4 rows)
Dalam versi PostgreSQL> 9.6, nilai default max_replication_slots adalah 10 yang diaktifkan secara default tetapi tidak dalam versi 9.6 atau lebih rendah yang dinonaktifkan secara default. Anda perlu menetapkan max_replication_slots lebih tinggi dari 0. Dalam contoh ini, saya menetapkan max_replication_slots ke 5.
[email protected]:~# grep 'max_replication_slots' /etc/postgresql/9.6/main/postgresql.conf
# max_replication_slots = 0 # max number of replication slots
max_replication_slots = 5
dan memulai ulang layanan,
[email protected]:~# pg_lsclusters
Ver Cluster Port Status Owner Data directory Log file
9.6 main 5432 online postgres /var/lib/postgresql/9.6/main pg_log/postgresql-%Y-%m-%d_%H%M%S.log
[email protected]:~# pg_ctlcluster 9.6 main restart
Mengatur Slot Replikasi Untuk Node Utama dan Siaga
Tidak ada opsi di ClusterControl untuk melakukan ini, jadi Anda harus membuat slot secara manual. Dalam contoh ini, saya membuat slot di utama di host 192.168.30.100:
192.168.10.100:5432 [email protected]_db=# SELECT pg_create_physical_replication_slot('slot1'), pg_create_physical_replication_slot('slot2');
pg_create_physical_replication_slot | pg_create_physical_replication_slot
-------------------------------------+-------------------------------------
(slot1,) | (slot2,)
(1 row)
Memeriksa acara yang baru saja kita buat,
192.168.10.100:5432 [email protected]_db=# select * from pg_replication_slots;
slot_name | plugin | slot_type | datoid | database | active | active_pid | xmin | catalog_xmin | restart_lsn | confirmed_flush_lsn
-----------+--------+-----------+--------+----------+--------+------------+------+--------------+-------------+---------------------
slot1 | | physical | | | f | | | | |
slot2 | | physical | | | f | | | | |
(2 rows)
Sekarang di node standby, kita perlu memperbarui recovery.conf dan menambahkan variabel primary_slot_name dan mengubah application_name sehingga lebih mudah untuk mengidentifikasi node. Berikut tampilannya di host 192.168.30.110 recovery.conf:
[email protected]:/var/lib/postgresql/9.6/main/pg_log# cat ../recovery.conf
standby_mode = 'on'
primary_conninfo = 'application_name=node11 host=192.168.30.100 port=5432 user=cmon_replication password=m8rLmZxyn23Lc2Rk'
recovery_target_timeline = 'latest'
primary_slot_name = 'slot1'
trigger_file = '/tmp/failover_5432.trigger'
Melakukan hal yang sama juga di host 192.168.30.120 tetapi mengubah application_name dan menyetel primary_slot_name ='slot2'.
Memeriksa kesehatan slot replikasi:
192.168.10.100:5432 [email protected]_db=# select * from pg_replication_slots;
slot_name | plugin | slot_type | datoid | database | active | active_pid | xmin | catalog_xmin | restart_lsn | confirmed_flush_lsn
-----------+--------+-----------+--------+----------+--------+------------+------+--------------+-------------+---------------------
slot1 | | physical | | | t | 24252 | | | 0/CF0A4218 |
slot2 | | physical | | | t | 11635 | | | 0/CF0A4218 |
(2 rows)
Apa Lagi yang Anda Butuhkan?
Karena ClusterControl tidak mendukung Slot Replikasi untuk saat ini, ada beberapa hal yang perlu Anda pertimbangkan. Apa ini? Mari kita masuk ke detailnya.
Proses Failover/Switchover
Bila failover otomatis atau peralihan melalui ClusterControl telah dicoba, slot tidak akan dipertahankan dari node utama dan node siaga. Anda perlu membuat ulang ini secara manual, memeriksa variabel jika disetel dengan benar, dan memodifikasi recovery.conf yang sesuai.
Membangun Kembali Budak dari Seorang Master
Saat membangun kembali slave, recovery.conf tidak akan disimpan. Ini berarti bahwa pengaturan recovery.conf Anda yang memiliki primary_slot_name akan dihapus. Anda perlu menentukan ini secara manual lagi dan memeriksa tampilan pg_replication_slots untuk menentukan apakah slot digunakan dengan benar atau dibiarkan kosong.
Jika Anda ingin membangun kembali node slave/standby dari master, Anda mungkin harus mempertimbangkan untuk menentukan variabel env PGAPPNAME seperti perintah di bawah ini:
$ export PGAPPNAME="app_repl_testnode15"; /usr/pgsql-9.6/bin/pg_basebackup -h 192.168.10.190 -U cmon_replication -D /var/lib/pgsql/9.6/data -p5434 -W -S main_slot -X s -R -P
Menentukan param -R sangat penting sehingga akan membuat ulang recovery.conf, sedangkan -S akan menentukan nama slot yang akan digunakan saat membangun kembali node siaga.
Kesimpulan
Menerapkan Slot Replikasi di PostgreSQL sangatlah mudah, namun ada beberapa peringatan yang harus Anda ingat. Saat menerapkan dengan ClusterControl, Anda harus memperbarui beberapa setelan selama failover atau pembuatan ulang slave.