L
JavaScript • Literally Web ID

High Availability PostgreSQL & Redis Replication untuk Backend SPA

⏱️ 18 menit baca • 📅 12 Oct 2026 • 👁️ 1 views
High Availability PostgreSQL & Redis Replication untuk Backend SPA

1. Konteks Industri & Analisis Akar Masalah

Dalam lanskap arsitektur web modern, Single Page Application (SPA) yang didukung oleh backend terdistribusi (Node.js, Go, PHP-FPM) sangat bergantung pada kecepatan dan ketahanan lapisan data. Ketika sebuah aplikasi SPA mengalami lonjakan trafik, titik kegagalan tunggal (Single Point of Failure / SPOF) pada basis data relasional seperti PostgreSQL atau pada in-memory cache seperti Redis akan langsung melumpuhkan seluruh sistem.

Secara historis, kegagalan paling umum dalam arsitektur backend SPA adalah lonjakan koneksi (connection storm) yang mendadak akibat ribuan klien SPA melakukan polling ulang secara bersamaan saat koneksi WebSocket terputus. Tanpa adanya connection pooling yang efisien, PostgreSQL akan kehabisan proses worker (max_connections), menyebabkan lonjakan latensi (latency spike), dan akhirnya memicu out-of-memory (OOM) killer pada sistem operasi.

Selain itu, ketersediaan tinggi (High Availability) pada lapisan data sering kali gagal diimplementasikan dengan benar. Banyak organisasi mengandalkan replikasi master-slave manual atau skrip bash kustom yang rapuh untuk melakukan failover. Akibatnya, ketika node master PostgreSQL mati, proses pemulihan manual memakan waktu berjam-jam (RTO yang tinggi) dan berisiko kehilangan data transaksi akibat inkonsistensi replikasi asynchronous.

Kondisi Sebelum vs Sesudah Penerapan

Metrik / Aspek Sebelum (SPOF / Konvensional) Sesudah (Patroni HA + Redis Cluster & Pooling)
Recovery Time Objective (RTO) 30 - 120 menit (Manual intervention) < 30 detik (Automated leader election via etcd)
Recovery Point Objective (RPO) Bergantung pada dump terakhir (Potensi kehilangan data) Mendekati nol (Synchronous/Quorum replication)
Kapasitas Koneksi Backend Langsung ke DB (Raw connection limit terlampaui) Dimitigasi melalui PgBouncer & Redis Caching Layer
Skalabilitas Baca (Read Scaling) Terbebankan pada satu instance master Didistribusikan ke multiple replica & Redis cluster

2. Konsep Inti & Deep Dive Arsitektur

Untuk membangun sistem yang tangguh, kita harus menggabungkan beberapa komponen enterprise: Patroni untuk orkestrasi PostgreSQL HA, etcd sebagai penyimpan konfigurasi terdistribusi dan distributed lock, PgBouncer untuk connection pooling, serta Redis Sentinel/Cluster untuk caching layer berperforma tinggi.

Visualisasi Arsitektur High Availability

+-------------------------------------------------------+
|               Single Page Application (SPA)           | 
+-------------------------------------------------------+
                           │
                           ▼
+-------------------------------------------------------+
|             Nginx Reverse Proxy / Load Balancer       |
+-------------------------------------------------------+
       │                                         │
       ▼                                         ▼
+-----------------------------+   +-----------------------------+ 
| Backend Service A (Go/Node) |   | Backend Service B (Go/Node) | 
+-----------------------------+   +-----------------------------+
       │               │                 │               │
       │ (Pool)        │ (Cache)         │ (Pool)        │ (Cache)
       ▼               ▼                 ▼               ▼
+-------------+  +------------+   +-------------+  +------------+
|  PgBouncer  |  |   Redis    |   |  PgBouncer  |  |   Redis    | 
+-------------+  |  Sentinel  |   +-------------+  |  Sentinel  |
       │         +------------+          │         +------------+
       │                                 │
       └────────────────┬────────────────┘
                        │
                        ▼
+-------------------------------------------------------+
|                   Patroni Cluster                     |
|  +-------------------+  +--------------------------+  |
|  | PostgreSQL Master |◄─┤ PostgreSQL Replica (Sync)|  |
|  +-------------------+  +--------------------------+  |
|           ▲                          ▲                |
|           └───────────┬──────────────┘                |
|                       ▼                               |
|                 +-----------+                         |
|                 |   etcd    |                         |
|                 +-----------+                         |
+-------------------------------------------------------+

Alur Kerja di Balik Layar (Under the Hood)

  1. Patroni & etcd: Setiap node PostgreSQL menjalankan agen Patroni. Patroni secara konstan berkomunikasi dengan kluster etcd untuk melakukan leader election. Node yang berhasil memegang lease di etcd akan diinisiasi sebagai PostgreSQL Master. Jika node master berhenti mengirim heartbeat ke etcd, lease kedaluwarsa, Patroni lain akan melakukan pemilihan, mempromosikan replika tersehat menjadi master baru secara otomatis.
  2. PgBouncer: Berada di antara aplikasi backend dan PostgreSQL. PgBouncer melakukan multiplexing ribuan koneksi klien dari backend menjadi sejumlah kecil koneksi permanen ke PostgreSQL menggunakan mode session, transaction, atau statement pooling.
  3. Redis Sentinel: Memantau kesehatan master dan slave Redis. Jika master Redis gagal, Sentinel secara otomatis melakukan failover dan memperbarui konfigurasi klien secara dinamis tanpa perlu restart aplikasi backend.

3. Perbandingan Komparatif / Analisis Pendekatan

Dalam merancang lapisan data caching untuk SPA, pemilihan antara Redis Sentinel dan Redis Cluster sangat krusial.

Parameter Perbandingan Redis Sentinel Redis Cluster
Arsitektur Master-Replika dengan pemantauan eksternal (Sentinel) Sharding otomatis terdistribusi tanpa proxy tunggal
Kapasitas Penyimpanan Dibatasi oleh kapasitas RAM satu mesin (Single Node Limit) Dapat diskalakan secara horizontal (Multi-Node Shards)
Kompleksitas Operasional Rendah hingga Sedang (Mudah di-deploy dan dipantau) Tinggi (Membutuhkan minimal 6 node: 3 master, 3 replika)
Failover Automation Otomatis via Sentinel Quorum Otomatis via Gossip Protocol antar node
Dukungan Multi-Key Operations Mendukung penuh semua perintah multi-key Dibatasi oleh Hash Tags ({user1000})
Rekomendasi Penggunaan Dataset < 32GB, fokus pada HA dan kemudahan operasional Dataset masif (> 64GB), kebutuhan throughput ekstrem

[!TIP] Untuk sebagian besar backend SPA skala menengah hingga besar, Redis Sentinel dikombinasikan dengan pembagian logika aplikasi (application-level sharding) jauh lebih stabil dan mudah di-debug dibandingkan Redis Cluster murni, kecuali Anda mengelola cache berukuran ratusan gigabyte.


4. Prasyarat Sistem & Persiapan Lingkungan

Sebelum memulai instalasi, pastikan Anda menyiapkan minimal 3 server mandiri (virtual machine atau bare-metal) untuk membentuk kuorum etcd dan Patroni yang andal (aturan kuorum: minimal 3 node untuk mencegah split-brain).

Spesifikasi Minimum Per Node

  • OS: Ubuntu 22.04 LTS / Debian 12 / RHEL 9
  • CPU: 4 vCPU
  • RAM: 8 GB - 16 GB
  • Storage: SSD NVMe (IOPS tinggi untuk WAL PostgreSQL)
  • Network: Jaringan lokal privat (VPC) dengan latensi < 2ms antar node

Prasyarat Paket & Dependensi

Jalankan perintah berikut pada semua node server:

# Perbarui sistem dan instal dependensi dasar
sudo apt-get update && sudo apt-get upgrade -y
sudo apt-get install -y curl vim git jq net-tools lsb-release gnupg software-properties-common

# Nonaktifkan swap untuk performa memori Redis dan PostgreSQL yang optimal
sudo swapoff -a
sudo sed -i '/ swap / s/^/#/' /etc/fstab

# Konfigurasi batas system limit untuk file descriptors
echo "postgres soft nofile 65536" | sudo tee -a /etc/security/limits.d/postgres.conf
echo "postgres hard nofile 65536" | sudo tee -a /etc/security/limits.d/postgres.conf

5. Panduan Implementasi Langkah demi Langkah

Langkah 1: Instalasi dan Konfigurasi etcd

etcd bertindak sebagai sumber kebenaran (source of truth) untuk kluster Patroni.

# Instal etcd di ketiga node (Contoh IP: 10.0.1.11, 10.0.1.12, 10.0.1.13)
SUBNET_IP="10.0.1.11"
NODE_NAME="etcd-node-1"

sudo apt-get install -y etcd-server etcd-client

# Buat konfigurasi /etc/etcd/etcd.conf
cat << 'EOF' | sudo tee /etc/etcd/etcd.conf
ETCD_NAME="etcd-node-1"
ETCD_DATA_DIR="/var/lib/etcd/etcd-node-1.etcd"
ETCD_LISTEN_PEER_URLS="http://10.0.1.11:2380"
ETCD_LISTEN_CLIENT_URLS="http://10.0.1.11:2379,http://127.0.0.1:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.0.1.11:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://10.0.1.11:2379"
ETCD_INITIAL_CLUSTER="etcd-node-1=http://10.0.1.11:2380,etcd-node-2=http://10.0.1.12:2380,etcd-node-3=http://10.0.1.13:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-postgres-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"
EOF

sudo systemctl restart etcd
sudo systemctl enable etcd

Langkah 2: Instalasi PostgreSQL & Patroni

Instal PostgreSQL dan pustaka Python yang dibutuhkan oleh Patroni.

# Tambahkan repository PostgreSQL resmi
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -

sudo apt-get update
sudo apt-get install -y postgresql-15 postgresql-client-15 python3-pip python3-psycopg2 python3-yaml

# Hentikan layanan default agar dikelola oleh Patroni
sudo systemctl stop postgresql
sudo systemctl disable postgresql

# Instal Patroni menggunakan pip
sudo pip3 install patroni[etcd3]

Buat file konfigurasi Patroni /etc/patroni/patroni.yml:

scope: pg-ha-cluster
namespace: /service
name: postgres-node-1

etcd3:
  hosts:
    - 10.0.1.11:2379
    - 10.0.1.12:2379
    - 10.0.1.13:2379

restapi:
  listen: 10.0.1.11:8008
  connect_address: 10.0.1.11:8008

bootstrap:
  dcs:
    ttl: 30
    loop_wait: 10
    retry_timeout: 10
    maximum_lag_on_failover: 1048576
    synchronous_mode: true
    postgresql:
      use_pg_rewind: true
      use_slots: true
      parameters:
        max_connections: 500
        shared_buffers: 2GB
        effective_cache_size: 6GB
        maintenance_work_mem: 512MB
        work_mem: 16MB
        min_wal_size: 1GB
        max_wal_size: 4GB
        checkpoint_completion_target: 0.9
        wal_buffers: 16MB
        default_statistics_target: 100

  initdb:
    - encoding: UTF8
    - data-checksums

  pg_hba:
    - host replication replicator 10.0.1.0/24 md5
    - host all all 127.0.0.1/32 md5
    - host all all 10.0.1.0/24 md5

postgresql:
  listen: 10.0.1.11:5432
  connect_address: 10.0.1.11:5432
  data_dir: /var/lib/postgresql/15/patroni
  bin_dir: /usr/lib/postgresql/15/bin
  pgpass: /var/lib/postgresql/.pgpass
  authentication:
    replication:
      username: replicator
      password: SuperSecureReplicationPassword123!
    superuser:
      username: postgres
      password: SuperSecurePostgresPassword123!

saver: true

Buat Systemd service untuk Patroni /etc/systemd/system/patroni.service:

[Unit]
Description=Patroni with PostgreSQL
After=network.target etcd.service

[Service]
Type=simple
User=postgres
Group=postgres
ExecStart=/usr/local/bin/patroni /etc/patroni/patroni.yml
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
TimeoutSec=30
Restart=no

[Install]
WantedBy=multi-user.target

Aktifkan layanan Patroni:

sudo chown -R postgres:postgres /etc/patroni
sudo systemctl daemon-reload
sudo systemctl enable patroni
sudo systemctl start patroni

Langkah 3: Konfigurasi PgBouncer untuk Connection Pooling

sudo apt-get install -y pgbouncer

Edit /etc/pgbouncer/pgbouncer.ini:

[databases]* = host=127.0.0.1 port=5432 auth_user=postgres

[pgbouncer]
listen_addr = *
listen_port = 6432
auth_type = md5
auth_file = /etc/pgbouncer/userlist.txt
admin_users = postgres
stats_users = monitoring

pool_mode = transaction
max_client_conn = 2000
default_pool_size = 50
min_pool_size = 10
reserve_pool_size = 5
reserve_pool_timeout = 5
log_connections = 0
log_disconnections = 0
log_pooler_errors = 1

Buat file otentikasi /etc/pgbouncer/userlist.txt:

"postgres" "md5xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
"app_user" "md5xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
sudo systemctl restart pgbouncer
sudo systemctl enable pgbouncer

Langkah 4: Konfigurasi Redis & Sentinel

sudo apt-get install -y redis-server

Edit /etc/redis/redis.conf (pastikan bind ke IP lokal dan atur password):

bind 0.0.0.0
protected-mode yes
port 6379
requirepass RedisSecretMasterPassword123!
masterauth RedisSecretMasterPassword123!
maxmemory 4gb
maxmemory-policy allkeys-lru

Konfigurasi Redis Sentinel di /etc/redis/sentinel.conf:

port 26379
sentinel monitor mymaster 10.0.1.11 6379 2
sentinel auth-pass mymaster RedisSecretMasterPassword123!
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 10000
sentinel parallel-syncs mymaster 1
sudo systemctl restart redis-server
sudo systemctl restart redis-sentinel
sudo systemctl enable redis-server redis-sentinel

6. Bedah Kode & Penjelasan Detail Baris Kunci

Mari kita bedah beberapa parameter krusial yang terdapat pada konfigurasi di atas:

  1. synchronous_mode: true (Patroni DCS):

    • Fungsi: Memaksa Patroni mengaktifkan replikasi sinkron PostgreSQL. Artinya, transaksi tidak akan dikonfirmasi sukses (commit) oleh master sebelum setidaknya satu node replika menerima dan menulis WAL (Write-Ahead Log) ke disk lokal mereka.
    • Dampak Salah Konfigurasi: Jika diatur ke false (asynchronous), performa tulis sedikit meningkat, namun Anda berisiko mengalami data loss saat terjadi failover mendadak pada master.
  2. pool_mode = transaction (PgBouncer):

    • Fungsi: Menentukan bagaimana PgBouncer mengelola koneksi klien. Dalam mode transaction, koneksi dikembalikan ke pool segera setelah sebuah blok transaksi (BEGIN ... COMMIT) selesai. Ini sangat ideal untuk backend SPA yang mengirimkan ribuan request HTTP singkat secara bersamaan.
    • Dampak Salah Konfigurasi: Jika menggunakan mode session dengan ribuan koneksi aktif dari Node.js/Go, limit max_connections pada PostgreSQL akan cepat tercapai karena koneksi dipegang terus menerus meskipun klien sedang idle.
  3. maxmemory-policy allkeys-lru (Redis):

    • Fungsi: Memberitahu Redis untuk secara otomatis menghapus kunci (eviction) yang paling jarang digunakan (LRU - Least Recently Used) di seluruh kunci yang ada ketika batas RAM (maxmemory) tercapai.
    • Dampak Salah Konfigurasi: Jika menggunakan noeviction, Redis akan menolak perintah tulis baru (OOM command not allowed when used memory > 'maxmemory') yang langsung menyebabkan error pada API backend SPA Anda.

7. Skenario Produksi & Studi Kasus Dunia Nyata

Studi Kasus: Sistem E-Commerce Flash Sale dengan 50.000 Konkurensi Pengguna SPA.

  • Tantangan: Saat tombol flash sale diklik serentak oleh puluhan ribu pengguna SPA, backend menerima 20.000 request per detik (RPS). Akses langsung ke database relasional untuk memeriksa stok produk akan melumpuhkan PostgreSQL.
  • Solusi Arsitektural:
    1. Caching & Deduplication di Redis: Permintaan cek stok dialihkan ke Redis menggunakan struktur data Hash dan perintah Lua Scripting untuk menjamin operasi atomik pengurangan stok (DECRBY).
    2. Write-Behind Batching: Backend Go mengumpulkan transaksi pembelian dalam memori (buffer) dan melakukan bulk insert ke PostgreSQL melalui PgBouncer setiap 500ms.
    3. Read Replicas Scaling: Query pembacaan katalog produk, profil pengguna, dan riwayat transaksi didistribusikan secara round-robin ke node replika PostgreSQL melalui koneksi pool terpisah.

8. Common Pitfalls, Anti-Patterns & Solusi

[!WARNING] Anti-Pattern 1: Mengabaikan Network Partition (Split-Brain) pada etcd

  • Kesalahan: Menjalankan kluster etcd hanya dengan 2 node.
  • Solusi: Selalu gunakan jumlah node ganjil minimal 3 atau 5 node agar algoritma konsensus Raft dapat memilih kuorum mayoritas dengan aman.

[!WARNING] Anti-Pattern 2: Koneksi Database Langsung Tanpa PgBouncer di Lingkungan Serverless/Containers

  • Kesalahan: Menghubungkan ribuan kontainer backend Node.js langsung ke port 5432 PostgreSQL.
  • Solusi: Selalu arahkan koneksi ke PgBouncer di port 6432. Batasi ukuran pool per instance kontainer agar total koneksi kumulatif tidak melampaui kapasitas server database.

9. Benchmark, Metrik Kinerja & Tuning Performa

Untuk menguji ketahanan kluster yang telah dibangun, gunakan alat load testing seperti k6 atau wrk. Berikut adalah skrip pengujian k6 untuk mensimulasikan trafik SPA:

import http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
  stages: [
    { duration: '30s', target: 500 },  // Ramp-up ke 500 pengguna
    { duration: '2m', target: 2000 },   // Pertahankan 2000 RPS
    { duration: '30s', target: 0 },    // Ramp-down
  ],
};

export default function () {
  const res = http.get('https://api.domain.com/v1/products/featured');
  check(res, {
    'status is 200': (r) => r.status === 200,
    'response time < 50ms': (r) => r.timings.duration < 50,
  });
  sleep(0.1);
}

Parameter Tuning Lanjutan (Kernel Linux /etc/sysctl.conf)

# Optimasi TCP stack untuk koneksi konkurensi tinggi
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15

# Optimasi memori virtual untuk database
vm.swappiness = 1
vm.overcommit_memory = 1

Apply konfigurasi kernel:

sudo sysctl -p

10. Checklist Penerapan Produksi & Kesimpulan

Sebelum meluncurkan infrastruktur ini ke lingkungan produksi publik, pastikan Anda memverifikasi item-item dalam checklist berikut:

  • Kluster etcd berjumlah ganjil (3/5 node) dan berjalan stabil dengan latensi < 2ms.
  • Patroni aktif dan verifikasi failover otomatis berhasil dilakukan (uji coba matikan node master secara paksa).
  • PgBouncer terkonfigurasi dengan mode transaction dan batasan max_client_conn sesuai kapasitas RAM.
  • Redis Sentinel memantau master dengan quorum yang benar dan password terautentikasi.
  • Firewall (UFW / iptables / AWS Security Groups) membatasi akses port database hanya dari IP internal backend dan PgBouncer.
  • Skrip backup otomatis harian (pg_dump / pg_basebackup) dikonfigurasi dan disimpan ke storage eksternal (S3 / MinIO).
  • Monitoring metrik (Prometheus & Grafana) terpasang untuk memantau CPU, RAM, IOPS, Replication Lag, dan jumlah koneksi aktif.

Dengan menerapkan arsitektur Patroni HA PostgreSQL dan Redis Sentinel caching layer secara tepat, backend SPA Anda akan memiliki pondasi infrastruktur yang sangat tangguh, skalabel, dan siap menghadapi lonjakan trafik enterprise kelas dunia.

🏷️ Tags: #Redis #High Availability #Postgresql #Database Architecture #Patroni