PostgreSQLでストリーミングレプリケーションしてみる

# ストリーミングレプリケーションとは
プライマリサーバーの更新情報を、リアルタイムでスタンバイサーバーへ転送し、プライマリサーバDBとスタンバイサーバーDBの状態を一致させ続けることを実現させる機能

# 仕組み
WAL (Write-Ahead Log) をスタンバイサーバーへ転送し、スタンバイサーバーでWALを適用させ、プライマリサーバDBと状態を一致させ続ける。
これらは、両サーバのファイルに設定することで下記のプロセスを起動させ実現させている。
※設定ファイルの内容はそれぞれで異なる

プライマリサーバ： wal sender　プロセス
スタンバイサーバー：wal receiver プロセス

[参考サイト](https://komari.co.jp/blog/12588/#i-8)
## 単語解説
- WAL (Write-Ahead Log) 
一言で言うと、DBの変更命令書みたいなものらしい。トランザクションログとも呼ばれる。
PostgreSQLでは、データの書き込みを下記のような順で実施している。
        
        1. WALファイルに変更内容を記載
        2. 共有バッファのデータを書き換える

つまり、初めからテーブルなどに変更を実施するわけではない。
つまり、WALファイルがあることで、
-　ディスクの書き込みの節約
-　障害などでマシンがダウンしても、復旧を実施できる

## 構成
[富士通の解説](https://www.fujitsu.com/jp/products/software/resources/feature-stories/postgres/article-index/streaming-replication1/)が参考になります


## 構築手順

### 構築環境
- プライマリサーバ : CentOS7
- スタンバイサーバ : CentOS7

### プライマリサーバの設定
#### postgresql.conf
- postgresql.confの編集
```
# vi /var/lib/pgsql/13/data/postgresql.conf
```
|オプション  |設定内容  |意味  |
|---|---|---|
|listen_addresses|0.0.0.0  |	listen状態にするIPアドレスを指定。デフォルトでは127.0.0.1(localhost)のみ接続を許可 |
|port|5432 |listen状態にするポート番号を指定|
|synchronous_standby_names  |db02  |マスターに接続するスタンバイサーバのapplication_nameを定義 |

- DB再起動
```
sudo systemctl restart postgresql-13
``` 
- 0.0.0.0 がLISTENかを確認
```
sudo ss -ano | grep 5432
```

### スタンバイサーバーの設定
#### スタンバイサーバーDBの初期化
```
# rm -rf ${PGDATA}/*
# pg_basebackup -R -D ${PGDATA} -h [マスターDBのIP]
```
#### primary_conninfo.auto.conf
- postgresql.confの編集
pg_basebackupコマンド実行によって、postgresql.auto.confが自動生成される。
この自動生成されたパラメタの末尾にapplication_nameを加筆する。
※application_nameは,プライマリサーバのpostgresql.conf記載のオプション「synchronous_standby_names」で定義した内容を入力する。
```
# vi /var/lib/pgsql/13/data/postgresql.auto.conf 

primary_conninfo = 'user=postgres ---中間略--- application_name=db02'

```

- postgresql.confの編集
postgresql.confファイルは、プライマリサーバのpostgresql.confがそのまま複製されているため、プライマリサーバ設定時に追記させた内容をコメントアウトさせる。

```
# vi /var/lib/pgsql/13/data/postgresql.conf
 --以下ファイルの編集対象行抜粋--
#listen_addresses = '0.0.0.0'
#port = 5432
#synchronous_standby_names = 'db01'
```
- DB再起動
再起動に成功したタイミングで、レプリケーションが開始される。
```
sudo systemctl restart postgresql-13
``` 

### レプリケーションの起動確認
上記までの動作でレプリケーションはすでに開始されているはずなので、起動の確認を実施する。
#### ログの確認
/var/lib/pgsql/13/data/log/直下に「postgresql-Fri.log」や「postgresql-Thu.log」というようなログが出力される。
ファイル名は曜日ごとに変わってくる。
コマンドは両サーバで下記を利用
```
less /var/lib/pgsql/13/data/log/postgresql-Thu.log 
```
- プライマリサーバ側
```
-略-
2022-07-07 19:02:11.168 JST [23567] LOG:  database system is ready to accept connections
2022-07-07 19:06:46.754 JST [23842] LOG:  standby "db02" is now a synchronous standby with priority 1
2022-07-07 19:06:46.754 JST [23842] STATEMENT:  START_REPLICATION 0/3000000 TIMELINE 1
-略-
```

- スタンバイサーバー側
```
-略-
2022-07-07 19:06:46.705 JST [2932] LOG:  redo starts at 0/2000028
2022-07-07 19:06:46.705 JST [2932] LOG:  consistent recovery state reached at 0/3000000
2022-07-07 19:06:46.706 JST [2928] LOG:  database system is ready to accept read only connections
2022-07-07 19:06:46.717 JST [2936] LOG:  started streaming WAL from primary at 0/3000000 on timeline 1
-略-
```
### レプリケーション動作確認
プライマリサーバDBでテーブルを１つ、作成後、スタンバイサーバー側のDBに同一のテーブルがあるかどうかを確認する。
今回は、問題なく存在したため、成功。

下記のサイトを参考
[PostgreSQL 13 ストリーミングレプリケーションの最小構成](https://changineer.info/server/postgresql/postgresql_streaming_replication01.html)

引用：[PostgreSQLの概要とアーキテクチャ](https://thinkit.co.jp/article/1038/1?page=0%2C2#:~:text=WAL%E3%81%AF%E3%80%81Write%20Ahead%20Logging,%E3%81%AB%E3%81%AF%E6%9B%B8%E3%81%8D%E8%BE%BC%E3%81%BF%E3%81%BE%E3%81%9B%E3%82%93%E3%80%82)

##