Chuyển đến nội dung chính

レッスン 2: PostgreSQL でのストリーミング レプリケーション

ストリーミング レプリケーション メカニズム、WAL ログ、同期/非同期レプリケーションの違いを調べ、基本的なプライマリ/スタンバイ セットアップを実践します。

レッスンの目的_

このレッスンを終えると、次のことができるようになります:

  • PostgreSQL のストリーミング レプリケーション メカニズムを理解する

  • マスター先行書き込みログ (WAL) とその役割_

  • 同期レプリケーションと非同期レプリケーションの区別

  • レプリケーションスロットの理解と使用

  • 手動レプリケーション設定の練習(プライマリ-スタンバイ)


1。ストリーミング レプリケーションの動作メカニズム

1.1。概要

ストリーミング レプリケーションは、PostgreSQL がプライマリ サーバーから 1 つ以上のスタンバイ サーバーにデータをリアルタイムでレプリケートする方法です。

ストリーミング レプリケーションの仕組み

1.2。主要コンポーネント_

_WAL 送信者 (プライマリ)_

  • _プロセスはスタンバイへの WAL レコードの送信に特化_

  • スタンバイごとに 1 つの WAL 送信者接続_

  • モニタリング: SELECT * FROM pg_stat_replication;

_WAL レシーバー (オン)スタンバイ)_

  • プロセスはプライマリから WAL レコードを受信_

  • WAL をローカル WAL ファイルに書き込み

  • プライマリにフィードバックを送信 (LSN)位置、ステータス)_

起動プロセス (スタンバイ時)

  • WAL レコードをデータ ファイルに再生_

  • _リカバリと同じプロセス_

  • 読み取りクエリを処理できます (ホットスタンバイ)

1.3。詳細なデータ フロー

トランザクション コミット フロー

リアルタイム実績:

  • 非同期: ~0 ~ 100 ミリ秒のラグ_

  • 同期: ~1 ~ 10 ミリ秒のラグ (ネットワーク遅延に応じて)


2。先行書き込みログ (WAL)

2.1。 WAL とは何ですか?

先行書き込みログ は、

「すべての変更はデータを書き込む前にログに書き込む必要がある」というログ技術です。ファイル"_

WAL 原則:

Write-Ahead ログ (WAL)

2.2。 WAL ファイルの構造

場所: $PGDATA/pg_wal/

$ ls -lh $PGDATA/pg_wal/
-rw------- 1 postgres postgres 16M Nov 24 10:00 000000010000000000000001
-rw------- 1 postgres postgres 16M Nov 24 10:15 000000010000000000000002
-rw------- 1 postgres postgres 16M Nov 24 10:30 000000010000000000000003

特殊ポイント:

  • 各ファイル: 16MB (デフォルト)

  • ファイル名: タイムライン ID + セグメント数値_

  • 形式: TTTTTTTTXXXXXXXXYYYYYYYY

    • TTTTTTTT: タイムライン (8 進数)桁)

    • XXXXXXXX: ログ ファイル番号 (8 進数)

    • YYYYYYYY: セグメント番号 (8 hex)_

2.3。 LSN (ログ シーケンス番号)

LSN は WAL ストリーム内の位置です。形式: X/Y

  • X: WAL ファイル番号

  • Y: ファイル内のオフセット

-- Kiểm tra LSN hiện tại
SELECT pg_current_wal_lsn();  -- Primary
-- Output: 0/3000060

SELECT pg_last_wal_receive_lsn(); -- Standby (received) SELECT pg_last_wal_replay_lsn(); -- Standby (applied)

2.4。 WAL 構成パラメータ

# postgresql.conf

WAL Settings

wal_level = replica # minimal, replica, or logical # replica: cho streaming replication

wal_log_hints = on # Cần thiết cho pg_rewind

WAL Writing

wal_buffers = 16MB # WAL buffer size trong shared memory wal_writer_delay = 200ms # WAL writer sleep time

WAL Files Management

min_wal_size = 80MB # Tối thiểu WAL files giữ lại max_wal_size = 1GB # Trigger checkpoint khi vượt

Checkpoints

checkpoint_timeout = 5min # Tối đa giữa 2 checkpoints checkpoint_completion_target = 0.9 # Spread checkpoint writes

2.5。 WAL とクラッシュリカバリ_

PostgreSQL がクラッシュした場合:

1. Server restart
2. PostgreSQL đọc last checkpoint location
3. Replay tất cả WAL records từ checkpoint → crash point
4. Khôi phục database về trạng thái consistent
5. Ready to accept connections

Wallet例:_

Timeline:
10:00 ─── Checkpoint ─── 10:05 ─── 10:08 (CRASH)
(LSN: 0/1000)          (LSN: 0/3000)

Recovery:

  • Bắt đầu từ LSN 0/1000
  • Replay WAL → LSN 0/3000
  • Database consistent tại 10:08

3。同期レプリケーションと非同期レプリケーション_

3.1。非同期レプリケーション (デフォルト)

仕組み:

非同期レプリケーション(デフォルト)

機能:

  • ✅ パフォーマンスが高い: プライマリは待機しませんスタンバイ

  • ✅ 低遅延: コミット時間はネットワークに依存しません

  • ❌ 失われる可能性がありますdata: スタンバイが WAL を受信する前にプライマリがクラッシュした場合

  • ❌ RPO > 0_: 目標復旧時点はゼロではありません

構成:

# postgresql.conf (Primary)
synchronous_commit = off  # hoặc local

使用ケース:

  • 別のデータセンターでスタンバイ (待ち時間が長い)

  • データよりもパフォーマンスを優先する安全性

  • 許容できるデータ損失 (数秒)

3.2。同期レプリケーション

仕組み:

同期レプリケーション

特殊ポイント:

  • ✅ データ損失ゼロ_: トランザクションはスタンバイ確認時のみコミット

  • ✅ RPO = 0: 重要なデータに最適

  • ❌ パフォーマンスへの影響: 各最大 2 ~ 10 ミリ秒のオーバーヘッドcommit

  • ❌ 可用性リスク: スタンバイの場合のプライマリ ブロック失敗

構成:_

# postgresql.conf (Primary)
synchronous_commit = on              # on, remote_write, remote_apply
synchronous_standby_names = 'standby1,standby2'  # Tên standbys

recovery.conf hoặc postgresql.auto.conf (Standby)

primary_conninfo = 'host=primary port=5432 user=replicator application_name=standby1'

同期コミットレベル:

HTMLT AG_332HTMLTAG_3 52H TMLTAG_393

remote_write

レベル

イタリアの意味

データ安全性

パフォーマンス

off

お待ちくださいスタンバイ

低

最高

__ HTMLTAG_375___local

ローカルディスクのみ待機

Central平均

曹

OS キャッシュへのスタンバイ書き込みを待つ

かなり良い_

中央平均

on

スタンバイ フラッシュを待つディスク

良い

もっとゆっくり

HTM LTAG_435___remote_apply

待機スタンバイ適用変更内容

最高

最も遅い

3.3.クォーラムベースの同期レプリケーション

PostgreSQL 9.6+: 柔軟な同期レプリケーション_

# Chờ ANY 1 trong 2 standbys
synchronous_standby_names = 'ANY 1 (standby1, standby2)'

Chờ FIRST 2 trong 3 standbys

synchronous_standby_names = 'FIRST 2 (standby1, standby2, standby3)'

Chờ ALL standbys (giống cũ)

synchronous_standby_names = 'standby1, standby2'

例: 任意1

3 Standbys: standby1 (DC1), standby2 (DC2), standby3 (DC3)

Transaction commit khi: ✅ Primary committed + ANY 1 standby acknowledged

Scenario:

  • standby1: ACK trong 5ms
  • standby2: ACK trong 100ms (slow network)
  • standby3: DOWN

→ Transaction commit sau 5ms (chờ standby1) → Performance tốt + Data safety

3.4。同期と非同期の比較

HTMLTAG_562

95-98%

HTMLTAG_57 8

高

Text will_

非同期

HTMLTA G_483___同期

コミットレイテンシー

~1ms

~5-10ms

データ損失のリスク

はい(一部)秒)

いいえ

HTMLTAG_522 RPO

秒

ゼロ

HTML AG_533

RTO

~30~60 代___HTM LTAG_544

~30~60代

HTMLTAG 549

第一次パフォーマンス

100%

ネットワーク依存関係

低

ユースケース

リードレプリカ、レポート

重要なデータ、財務


4。レプリケーション スロット

4.1。レプリケーション スロットの前の問題

シナリオ:

1. Primary generates WAL files
2. Checkpoint happens → Old WAL cleaned up
3. Standby offline vài giờ
4. Standby comes back online
5. ❌ WAL files needed đã bị xóa
6. ❌ Standby không thể catch up
7. ❌ Cần rebuild Standby từ đầu

4.2。レプリケーション スロットが問題を解決します

レプリケーション スロット は、スタンバイが消費されるまでプライマリが WAL ファイルを保持することを保証します。

レプリケーションスロット

4.3。レプリケーション S の作成と管理ロット

プライマリにスロットを作成:

-- Physical replication slot
SELECT * FROM pg_create_physical_replication_slot('standby1_slot');

-- Xem danh sách slots SELECT slot_name, slot_type, active, restart_lsn, confirmed_flush_lsn FROM pg_replication_slots;

-- Output: slot_name | slot_type | active | restart_lsn | confirmed_flush_lsn ---------------+-----------+--------+-------------+-------------------- standby1_slot | physical | t | 0/3000000 | NULL

上記のスロットを使用スタンバイ:

ini

# postgresql.auto.conf (Standby)
primary_slot_name = 'standby1_slot'

削除スロット:

sql_

SELECT pg_drop_replication_slot('standby1_slot');

4.4。レプリケーション スロットの監視_

sql

-- Kiểm tra slot status
SELECT
slot_name,
active,
pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) as retained_wal
FROM pg_replication_slots;

-- Cảnh báo nếu retained_wal quá lớn (>10GB)

4.5。重要な注意事項_

⚠️ リスク:

  • スタンバイがスロットで長時間オフラインの場合 → プライマリが WAL を維持する永久

  • プライマリのディスクをいっぱいにすることができます

  • 監視とアラートが必要

最高練習:

sql

-- Set max WAL size để bảo vệ Primary
ALTER SYSTEM SET max_slot_wal_keep_size = '100GB';  -- PostgreSQL 13+

-- Hoặc tự động drop inactive slot sau 24h SELECT pg_drop_replication_slot(slot_name) FROM pg_replication_slots WHERE NOT active AND pg_current_wal_lsn() - restart_lsn > 10010241024*1024; -- 100GB


5。ラボ: ストリーミング レプリケーションを手動でセットアップ

5.1。ラボの目標

次の PostgreSQL クラスターを作成します:

  • 1 プライマリ サーバー

  • 1 スタンバイサーバー_

  • ストリーミングレプリケーション(非同期)

  • ホットスタンバイ(読み取りクエリ)

5.2。環境

Primary:  192.168.1.101 (node1)
Standby:  192.168.1.102 (node2)
PostgreSQL: 14
OS: Ubuntu 22.04

5.3。ステップ 1: PostgreSQL をインストールします (両方のノード)

bash

# Install PostgreSQL 14
sudo apt update
sudo apt install -y postgresql-14 postgresql-contrib-14

Stop service

sudo systemctl stop postgresql

5.4。ステップ 2: プライマリ (node1) の構成

レプリケーションの作成ユーザー:

bash

sudo -u postgres psql

_sql

-- Tạo user cho replication
CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'repl_password';

-- Exit \q

構成postgresql.conf:

_bash

sudo nano /etc/postgresql/14/main/postgresql.conf

ini

# Connection
listen_addresses = '*'
port = 5432

Replication

wal_level = replica max_wal_senders = 5 max_replication_slots = 5 wal_keep_size = 1GB

Hot Standby (không cần cho primary nhưng tốt để có sẵn)

hot_standby = on

Archive (optional, recommended)

archive_mode = on archive_command = 'test ! -f /var/lib/postgresql/14/archive/%f && cp %p /var/lib/postgresql/14/archive/%f'

アーカイブの作成ディレクトリ:

bash

sudo mkdir -p /var/lib/postgresql/14/archive
sudo chown postgres:postgres /var/lib/postgresql/14/archive

構成pg_hba.conf:

bash

sudo nano /etc/postgresql/14/main/pg_hba.conf

ini

# Replication connections
host    replication     replicator      192.168.1.102/32        md5
host    replication     replicator      127.0.0.1/32            md5

開始プライマリ:

bash

sudo systemctl start postgresql
sudo systemctl status postgresql

レプリケーションの作成スロット:

bash

sudo -u postgres psql

sql

SELECT pg_create_physical_replication_slot('standby_slot');
SELECT * FROM pg_replication_slots;
\q

5.5。ステップ 3: スタンバイ (ノード 2) のセットアップ

PostgreSQL を停止し、古いデータをバックアップします:

bash

sudo systemctl stop postgresql
sudo mv /var/lib/postgresql/14/main /var/lib/postgresql/14/main.bak

ベース バックアッププライマリ:

bash

# Sử dụng pg_basebackup
sudo -u postgres pg_basebackup 
-h 192.168.1.101
-D /var/lib/postgresql/14/main
-U replicator
-P
-v
-R
-X stream
-C -S standby_slot

Options giải thích:

-h: Primary host

-D: Data directory

-U: Replication user

-P: Show progress

-v: Verbose

-R: Tạo standby.signal và postgresql.auto.conf

-X stream: Stream WAL during backup

-C: Create replication slot

-S: Slot name

出力サンプル:

pg_basebackup: initiating base backup, waiting for checkpoint to complete

pg_basebackup: checkpoint completed pg_basebackup: write-ahead log start point: 0/2000028 on timeline 1 pg_basebackup: starting background WAL receiver pg_basebackup: created replication slot "standby_slot" 24567/24567 kB (100%), 1/1 tablespace pg_basebackup: write-ahead log end point: 0/2000100 pg_basebackup: syncing data to disk ... pg_basebackup: base backup completed

standby.signal が有効であることを確認します。作成:

bash

ls -l /var/lib/postgresql/14/main/standby.signal

File này đánh dấu đây là standby server

Check postgresql.auto.conf:

bash

sudo cat /var/lib/postgresql/14/main/postgresql.auto.conf

ini

# Được tạo tự động bởi pg_basebackup -R

primary_conninfo = 'user=replicator password=repl_password host=192.168.1.101 port=5432 sslmode=prefer sslcompression=0 krbsrvname=postgres target_session_attrs=any' primary_slot_name = 'standby_slot'

開始スタンバイ:

bash

sudo systemctl start postgresql
sudo systemctl status postgresql

5.6。ステップ 4: レプリケーションの確認_

プライマリ (ノード 1):

sql

sudo -u postgres psql

-- Kiểm tra replication status SELECT client_addr, state, sync_state, replay_lsn, pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn)) as lag FROM pg_stat_replication;

-- Output: client_addr | state | sync_state | replay_lsn | lag ---------------+-----------+------------+-------------+------- 192.168.1.102 | streaming | async | 0/3000060 | 0 bytes

スタンバイ(ノード 2):

sql

sudo -u postgres psql

-- Kiểm tra standby status SELECT pg_is_in_recovery(); -- Should return 't' (true)

-- Kiểm tra replication lag SELECT pg_last_wal_receive_lsn() AS receive, pg_last_wal_replay_lsn() AS replay, pg_size_pretty(pg_wal_lsn_diff(pg_last_wal_receive_lsn(), pg_last_wal_replay_lsn())) AS lag;

-- Output: receive | replay | lag -------------+-------------+-------- 0/3000060 | 0/3000060 | 0 bytes

_5.7。ステップ 5: レプリケーションのテスト

プライマリ上 - テスト データの作成:

sql

-- Tạo database và table
CREATE DATABASE testdb;
\c testdb

CREATE TABLE users ( id SERIAL PRIMARY KEY, name VARCHAR(100), created_at TIMESTAMP DEFAULT NOW() );

INSERT INTO users (name) VALUES ('Alice'), ('Bob'), ('Charlie');

SELECT * FROM users;

スタンバイ上 - 確認データ:

sql

\c testdb

-- Read queries hoạt động SELECT * FROM users;

-- Output: id | name | created_at ----+---------+------------------------ 1 | Alice | 2024-11-24 10:30:15 2 | Bob | 2024-11-24 10:30:15 3 | Charlie | 2024-11-24 10:30:15

-- Write queries bị reject INSERT INTO users (name) VALUES ('David'); -- ERROR: cannot execute INSERT in a read-only transaction

5.8。ステップ 6: クエリの監視

レプリケーション遅延監視:

sql

-- Trên Primary
CREATE OR REPLACE FUNCTION replication_lag_bytes()
RETURNS TABLE(client_addr INET, lag_bytes BIGINT) AS $$
BEGIN
RETURN QUERY
SELECT
c.client_addr,
pg_wal_lsn_diff(pg_current_wal_lsn(), c.replay_lsn)::BIGINT
FROM pg_stat_replication c;
END;
$$ LANGUAGE plpgsql;

-- Sử dụng SELECT * FROM replication_lag_bytes();

遅延が発生した場合のアラート10MB:

sql

SELECT client_addr,
pg_size_pretty(lag_bytes) as lag
FROM replication_lag_bytes()
WHERE lag_bytes > 1010241024;

5.9。一般的な問題のトラブルシューティング

問題 1: スタンバイがプライマリに接続できない

bash

# Check logs
sudo tail -f /var/lib/postgresql/14/main/log/postgresql-*.log

Common errors:

- "FATAL: password authentication failed"

→ Check pg_hba.conf và password

- "FATAL: no pg_hba.conf entry for replication"

→ Add replication entry vào pg_hba.conf

- Connection refused

→ Check firewall, listen_addresses

問題 2: レプリケーションの遅延が増加する高_

sql

-- Kiểm tra WAL sender busy

SELECT * FROM pg_stat_activity WHERE backend_type = 'walsender';

-- Kiểm tra I/O trên Standby SELECT * FROM pg_stat_bgwriter;

問題 3: スロットが埋まっていますディスク

sql

-- Kiểm tra retained WAL
SELECT
slot_name,
pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) as retained
FROM pg_replication_slots;

-- Drop inactive slot nếu cần SELECT pg_drop_replication_slot('standby_slot');


6。ベスト プラクティス

6.1。構成のチューニング

ini

# Primary - postgresql.conf

Network buffer (nếu có nhiều standbys)

max_wal_senders = 10 # Tùy số standbys + 2 dự phòng

WAL retention

wal_keep_size = 2GB # Giữ đủ WAL cho standby catch up max_slot_wal_keep_size = 10GB # Limit slot retention (PG 13+)

Archive (backup strategy)

archive_mode = on archive_command = 'cp %p /backup/archive/%f'

Checkpoint tuning

checkpoint_timeout = 15min checkpoint_completion_target = 0.9

6.2。監視チェックリスト____HTMLTAG_854__HTMLTAG_855___✅ レプリケーションラグ (バイトと時間) ✅ スタンバイ接続ステータス ✅ WAL 送信プロセス ✅ ディスク容量 (pg_wal/およびarchive/) ✅ レプリケーションスロット (保持されたWAL) ✅ チェックポイントのパフォーマンス

6.3。セキュリティに関する推奨事項_

ini

# Use SSL for replication
ssl = on
ssl_cert_file = '/path/to/server.crt'
ssl_key_file = '/path/to/server.key'

Standby connection string

primary_conninfo = '... sslmode=require sslcompression=1'

ini

# pg_hba.conf - Use hostssl
hostssl replication replicator 192.168.1.0/24 md5

7。概要

重要なポイント_

  1. ストリーミング レプリケーション_ は PostgreSQL HA の基盤です:

    • リアルタイムWAL ストリーミング

    • 読み取りクエリのホット スタンバイ__HTMLTAG_893___

    • Patroni 自動フェイルオーバーの基礎

  2. WAL (先行書き込み)ログ):

    • データ書き込み前のログ

    • クラッシュ回復メカニズム

    • レプリケーショントランスポートformat

  3. 同期 vs 非同期:

    • 非同期: 高パフォーマンス、失われる可能性ありデータ_

    • Sync: データ損失ゼロ、パフォーマンスへの影響

    • クォーラムベース: 2 つの間のバランス

  4. レプリケーションスロット:

    • WAL が削除されていないことを確認してください時期尚早

    • スタンバイの安定性にとって重要

    • ディスクを回避するために監視が必要フル_