こちらの続き
VarnishのSaaSであるfastlyでは、VCLがVarnish2.1準拠 そのため、Varnish2.1での処理の流れを改めて把握して、図に書いた
Varnish 2.1のサブルーチンの流れ
エラーやrestatなど、正常処理以外の流れは端折っているので注意
ポイント
- 6.0 よりだいぶシンプル
- return する値も結構異なっている
- vcl_hash は、
req.hash+=
で hash のキーを定義する
参考
👇 v2.1 のサブルーチンの解説
こちらの続き
VarnishのSaaSであるfastlyでは、VCLがVarnish2.1準拠 そのため、Varnish2.1での処理の流れを改めて把握して、図に書いた
エラーやrestatなど、正常処理以外の流れは端折っているので注意
req.hash+=
で hash のキーを定義する👇 v2.1 のサブルーチンの解説
Varyヘッダ
(後述) の組み合わせをキーにしてcacheが行われるvcl_recv
でcacheの可否。vcl_hash
でhashのキーの定義ができるVary: Accept-Encoding
ならば、Varnish側のhashキーが同一でも Accept-Encoding
が異なるRequestは別の情報としてcacheされるサブルーチンによって、使えたり使えなかったりするので注意
hash
, pass
, pipe
のいずれかを return
の引数に入れるvcl_cache
が呼びだされるvcl_pass
が呼び出されるvcl_pipe
が呼び出されるvcl_recv
が return(pipe)
したら来るvcl_recv
が return(pass)
したら来るreturn(fetch)
すれば、オリジンサーバに問い合わせをする直前のサブルーチン vcl_backend_fetch
が呼び出されるvcl_recv
が return(hash)
したら来るvcl_hash
では、そのhashを取り出すためのキーを定義するhash_data
に値を追加していって、その値の組み合わせがキーになるreturn (lookup)
するvcl_hit
。無ければ、vcl_miss
が呼び出されるこの場合、リクエストURLと、ホスト(もしくはipアドレス)の組み合わせがhashのキーとなっている
sub vcl_hash { hash_data(req.url); if (req.http.host) { hash_data(req.http.host); } else { hash_data(server.ip); } return (lookup); }
ここに、webサービスの特性に応じてhash_dataを設定していく
return(deliver)
すれば、vcl_deliver
(cacheをクライアントにわたす直前のサブルーチン) が呼び出されるreturn(miss)
すれば、vcl_miss
(cacheがヒットしなかった場合のサブルーチン) が呼び出されるreturn(fetch)
すれば、オリジンサーバに問い合わせをする直前のサブルーチン vcl_backend_fetch
が呼び出されるreturn(fetch)
すれば、オリジンサーバに問い合わせた後、vcl_backend_response
が呼び出されるreturn(deliver)
すれば、vcl_deliver
(cacheをクライアントにわたす直前のサブルーチン) が呼び出されるvcl_hit
か vcl_backend_response
の後に呼び出されるreturn(deliver)
すると、クライアントにcacheが渡される👇 弊社blog記事。最初に読むと概要をつかみやすい
👇 v3.0.1 時代に作られたわかりやすい同人誌
👇 公式ドキュメントのサブルーチンの流れの解説
👇 公式ドキュメントのサブルーチンの解説
これの続き
postgres
ユーザにパスワードを設定postgresql.conf
に設定postgres
ユーザでアクセスするために、pg_hba.conf
を設定$ wget https://download.postgresql.org/pub/repos/yum/9.3/redhat/rhel-6-x86_64/pgdg-ami201503-93-9.3-3.noarch.rpm $ sudo rpm -ivh pgdg-ami201503-93-9.3-3.noarch.rpm $ sudo yum -y install postgresql93-server.x86_64 $ sudo chkconfig postgresql-9.3 on $ sudo service postgresql-9.3 initdb -E UTF-8 --no-locale $ sudo service postgresql-9.3 start
$ sudo su - postgres $ createdb mydb $ psql mydb
CREATE TABLE weather ( city varchar(80), temp_lo int, -- 最低気温 temp_hi int, -- 最高気温 prcp real, -- 降水量 date date ); INSERT INTO weather VALUES ('San Francisco', 46, 50, 0.25, '1994-11-27');
postgres
ユーザにパスワードを設定$ sudo su - postgres $ psql
alter role postgres with password 'password';
本当はもっと強固なパスワードにすべき
postgresql.conf
に設定デフォルトの設定との差分は以下の通り
$ diff /var/lib/pgsql/9.3/data/postgresql.conf.bak /var/lib/pgsql/9.3/data/postgresql.conf 59c59 < #listen_addresses = 'localhost' # what IP address(es) to listen on; --- > listen_addresses = '*' # what IP address(es) to listen on; 159c159 < #wal_level = minimal # minimal, archive, or hot_standby --- > wal_level = hot_standby # minimal, archive, or hot_standby 188c188 < #archive_mode = off # allows archiving to be done --- > archive_mode = on # allows archiving to be done 190c190,191 < #archive_command = '' # command to use to archive a logfile segment --- > archive_command = 'test ! -f /usr/local/pgsql/backup/%f && cp %p /usr/local/pgsql/backup/%f' > # command to use to archive a logfile segment 206c207 < #max_wal_senders = 0 # max number of walsender processes --- > max_wal_senders = 3 # max number of walsender processes 215c216 < #synchronous_standby_names = '' # standby servers that provide sync rep --- > synchronous_standby_names = 'slave' # standby servers that provide sync rep
それぞれの設定値の説明
listen_addresses
: 外部からのアクセスを許可する設定(*
ですべてのIPからのアクセスを許可)wal_level
: WALの保存レベルの設定archive_mode
: on
にすると、WALアーカイブプロセスが起動するようになるarchive_command
: WALアーカイブ時に実行されるコマンドmax_wal_senders
: WALを外部に送信するプロセスの最大数
synchronous_standby_names
: 同期スタンバイの名前(あとでスタンバイ側でも定義する)$ sudo mkdir -p /usr/local/pgsql/backup/ $ sudo chown postgres:postgres /usr/local/pgsql/backup
postgres
ユーザでアクセスするために、pg_hba.conf
を設定接続方法\t接続するDB\tuser\tIPアドレス\t認証方法
詳しくは公式ドキュメント → pg_hba.confファイル
デフォルトの設定との差分は以下の通り
$ diff /var/lib/pgsql/9.3/data/pg_hba.conf /var/lib/pgsql/9.3/data/pg_hba.conf.bak 90,91d89 < host replication postgres 172.16.0.0/12 md5 < host all postgres 172.16.0.0/12 md5
レプリケーション用の設定(1行目)と、普通にDBにアクセスする設定(2行目)も追加
replication
はレプリケーション用の特別な設定md5
はパスワード認証$ sudo service postgresql-9.3 restart
$ wget https://download.postgresql.org/pub/repos/yum/9.3/redhat/rhel-6-x86_64/pgdg-ami201503-93-9.3-3.noarch.rpm $ sudo rpm -ivh pgdg-ami201503-93-9.3-3.noarch.rpm $ sudo yum -y install postgresql93-server.x86_64 $ sudo chkconfig postgresql-9.3 on
直接 $PG_DATAを上書き
$ sudo su - postgres $ rm -rf $PGDATA $ pg_basebackup -h 172.31.59.13 -D $PGDATA -x -P -U postgres -R
-R
オプションで、後述の recovery.conf
を自動生成してくれるスタンバイサーバの設定は、 recovery.conf
に書く
なんで recovery.conf
に書くかというと、どうやら、PostgreSQLのレプリケーションとは、マスタデータから来たデータを元にDBをリカバリし続けるという方法のため、リカバリの設定を書く所に書くようになったっぽい
$ sudo su - postgres $ vim /var/lib/pgsql/9.3/data/recovery.conf
standby_mode = 'on' primary_conninfo = 'user=postgres host=172.31.59.13 port=5432 sslmode=prefer sslcompression=1 krbsrvname=postgres application_name=slave'
primary_conninfo
はDBに接続する時の接続文字列を定義
pg_basebackup
で自動生成された内容に加えて、同期レプリケーションのため、master の postgresql.conf
で定義した application_name=slave
を追記primary_conninfo
について、詳しくは → データベース接続制御関数#接続文字列hot_standby = on
だけ追記
$ sudo service postgresql-9.3 start
マスタ側で実行
$ sudo su - postgres $ psql
postgres-# \x Expanded display is on. postgres=# SELECT * FROM pg_stat_replication; -[ RECORD 1 ]----+------------------------------ pid | 356 usesysid | 10 usename | postgres application_name | slave client_addr | 172.31.57.96 client_hostname | client_port | 34172 backend_start | 2019-01-01 09:40:25.070405+00 state | streaming sent_location | 0/30002A8 write_location | 0/30002A8 flush_location | 0/30002A8 replay_location | 0/30002A8 sync_priority | 1 sync_state | sync
172.31.57.96
と、同期 sync_state: sync
のレプリケーションができていることが確認できた$ sudo su - postgres $ psql mydb
mydb=# SELECT * FROM weather; city | temp_lo | temp_hi | prcp | date ---------------+---------+---------+------+------------ San Francisco | 46 | 50 | 0.25 | 1994-11-27 (1 row)
$ sudo su - postgres $ psql mydb
mydb=# INSERT INTO weather VALUES ('Tokyo', 46, 50, 0.25, '1994-11-27'); INSERT 0 1
mydb=# SELECT * FROM weather; city | temp_lo | temp_hi | prcp | date ---------------+---------+---------+------+------------ San Francisco | 46 | 50 | 0.25 | 1994-11-27 Tokyo | 46 | 50 | 0.25 | 1994-11-27 (2 rows)
カラムが追加された! 👏
mydb=# INSERT INTO weather VALUES ('hoge', 46, 50, 0.25, '1994-11-27'); ERROR: cannot execute INSERT in a read-only transaction
エラーになることを確認
PostgreSQLのバックアップは3種類
$PG_DATA
のファイルをまるまるコピーする方法rsync を利用する(特にPostgreSQL由来のコマンドは使用しない)
バックアップ
$BACKUP
は、バックアップファイル格納PATH$ async -av $PGDATA/ $BACKUP/pgdata
リストア
$ rm -rf $PGDATA $ async -av $BACKUP/pgdata $PGDATA/
pg_dump
コマンドを実行する
pg_dump
コマンドは以下の形式でdumpが可能
バックアップ
リモートからもバックアップ可能
-Fc
はカスタムアーカイブ形式の指定$ pg_dump -Fc ${database_name} -U ${user_name} -h ${host_name} -f $BACKUP/dump.custom
リストア
$ pg_restore -d ${database_name} $BACKUP/dump.custom
ポイント
手順
(PostgreSQLを停止した状態で実施する)
WALアーカイブを保存するように設定
postgresql.conf
に以下の設定をする
wal_level = archive archive_mode = on archive_command = 'test ! -f /usr/local/pgsql/backup/%f && cp %p /usr/local/pgsql/backup/%f'
wal_level
: WALの保存レベル。以下の3種類がある
minial
: クラッシュまたは即時停止から回復するのに必要な情報のみ書き出す(デフォルト)replica
: WALアーカイブに対応。ストリーミングレプリケーションに必要な情報も追加
archive
と hot_standby
という別々の設定が統一されたlogical
: ロジカルレプリケーションをサポートするのに必要な情報も追加archive_mode
: WALアーカイブを許可する設定。デフォルトOFF
on
にすると、アーカイブプロセスが立ち上がるようになるarchive_command
: WALを破棄する時に実行されるコマンド
%p
はバックアップすべきWALのパス。 %f
はWALファイル名ベースバックアップの実行
$ pg_basebackup -D $BACKUP -F t -x -z
-F
: ファイルフォーマットの指定。t
はtar形式の保存。デフォルトは p
でプレーンテキストで保存される-z
: 出力ファイルをzip圧縮する-x
: ベースバックアップ作成中、出力ファイルの更新を止める(メモリを食うので注意ベースバックアップからの復旧
既存のデータからWALだけ避難
$ mv $PGDATA/pg_wal/ $BACKUP_WAL
既存のデータは不要なので移動
$ mv $PGDATA/pg_wal/ ${適当なバックアップ先}
ベースバックアップからの復旧
(tar.gz を解凍してから)
$ cp $BACKUP/pgdata/* $PGDATA
WALを最新のものに変更
(ベースバックアップのWALは古いので消す)
$ rm -rf $PGDATA/pg_wal/ $ cp $BACKUP_WAL $PGDATA/pg_wal
recovery.conf の設定
restore_command = 'cp /usr/local/pgsql/backup/%f %p' recovery_target_time = '2018/12/01 00:47:00'
restore_command
: archive_command
と逆に、WALアーカイブからcopyするコマンドを設定recovery_target_time
: PITRしたい場合、その時刻を設定する
www.slideshare.net
現在は以下の2種類をサポート
どちらもWALをスタンバイに渡すことでレプリケーションが行われている
今回はストリーミングレプリケーションについて詳しく掘り下げる
PostgreSQL9.0(2010年)まで、公式のレプリケーション機能は未サポートだった
なお、自動フェイルオーバーやリードレプリカへの振り分けは今も未サポート
wal_sender
スタンバイは wal_receiver
が行うストリーミングレプリケーションでは、設定ファイルでデフォルトのデータ保護レベルを設定可能
なお、トランザクション毎にも設定可能(らしい
スタンバイにさらにレプリケーションを貼ることで、レプリケーションのチェインが可能
これをカスケードレプリケーションと言う
www.slideshare.net
諸事情あって、EC2 on PostgreSQL 9.3 を知る必要があるので、ひとまず環境を作成してみる
適当に web UI から Amazon linux の t2.small を作成
それぞれ、EC2環境にsshして実行している
PostgreSQL は yumリポジトリの設定ファイルをrpmで配布しているので、それを取得する
$ wget https://download.postgresql.org/pub/repos/yum/9.3/redhat/rhel-6-x86_64/pgdg-ami201503-93-9.3-3.noarch.rpm
rpmのインストール
$ sudo rpm -ivh pgdg-ami201503-93-9.3-3.noarch.rpm
yumリポジトリが追加されたことを確認
$ rpm -ql pgdg-ami201503-93-9.3-3.noarch /etc/pki/rpm-gpg /etc/pki/rpm-gpg/RPM-GPG-KEY-PGDG-93 /etc/yum.repos.d/pgdg-93-ami201503.repo
追加された postgresql93
関係のパッケージを確認
$ sudo yum list all postgresql93* 読み込んだプラグイン:extras_suggestions, langpacks, priorities, update-motd 14 packages excluded due to repository priority protections 利用可能なパッケージ postgresql93.x86_64 9.3.25-1PGDG.rhel6 pgdg93 postgresql93-contrib.x86_64 9.3.25-1PGDG.rhel6 pgdg93 postgresql93-debuginfo.x86_64 9.3.25-1PGDG.rhel6 pgdg93 postgresql93-devel.x86_64 9.3.25-1PGDG.rhel6 pgdg93 postgresql93-docs.x86_64 9.3.25-1PGDG.rhel6 pgdg93 postgresql93-libs.x86_64 9.3.25-1PGDG.rhel6 pgdg93 postgresql93-odbc.x86_64 10.03.0000-1PGDG.rhel6 pgdg93 postgresql93-odbc-debuginfo.x86_64 09.03.0400-1PGDG.rhel6 pgdg93 postgresql93-plperl.x86_64 9.3.25-1PGDG.rhel6 pgdg93 postgresql93-plpython.x86_64 9.3.25-1PGDG.rhel6 pgdg93 postgresql93-pltcl.x86_64 9.3.25-1PGDG.rhel6 pgdg93 postgresql93-server.x86_64 9.3.25-1PGDG.rhel6 pgdg93 postgresql93-tcl.x86_64 2.4.0-1.rhel6 pgdg93 postgresql93-tcl-debuginfo.x86_64 2.3.1-1.rhel6 pgdg93 postgresql93-test.x86_64 9.3.25-1PGDG.rhel6 pgdg93
yum install postgresql-server
すれば、必要なものはすべてインストールされるらしいので、それに従う
$ sudo yum -y install postgresql93-server.x86_64
結果、以下のパッケージがインストールされた
インストール中: postgresql93-server x86_64 9.3.25-1PGDG.rhel6 pgdg93 4.1 M 依存性関連でのインストールをします: postgresql93 x86_64 9.3.25-1PGDG.rhel6 pgdg93 1.0 M postgresql93-libs x86_64 9.3.25-1PGDG.rhel6 pgdg93 198 k
PostgreSQLをインストールすると、postgresql userが追加されるので、それを確認
$ id postgres uid=26(postgres) gid=26(postgres) groups=26(postgres)
serviceをONにする
$ sudo chkconfig postgresql-9.3 on $ chkconfig --list postgresql-9.3 注記: この出力に含まれるのは SysV サービスのみです。ネイティブな systemd サービスは含まれません。SysV の設定データはネイティブな systemd 設定で上書きされる場合があります。 systemd サービスを一覧表示する場合は 'systemctl list-unit-files' を使用します。 特定のターゲットで有効になっているサービスを確認する場合は 'systemctl list-dependencies [target]'を使用します。 postgresql-9.3 0:off 1:off 2:on 3:on 4:on 5:on 6:off
initdb
$ sudo service postgresql-9.3 initdb -E UTF-8 --no-locale
-E
はエンコードの指定。明示的に指定しないと、起動環境のエンコードを引き継ぐので、UTF-8を明示的に指定--no-locale
はロケールの指定。こちらも明示的にロケールを引き継がないようにしている(ソート順などに影響がでるらしい起動
$ sudo service postgresql-9.3 start
本当はこの後にアクセス制限を設定する必要があるが割愛
$ sudo su - postgres $ createuser ec2-user
DB作成権限を付与
$ psql
postgres=# ALTER ROLE "ec2-user" WITH CREATEDB; ALTER ROLE
権限が付与されたことを確認
postgres=# \du List of roles Role name | Attributes | Member of -----------+------------------------------------------------+----------- ec2-user | Create DB | {} postgres | Superuser, Create role, Create DB, Replication | {}
ec2-user で実行
$ createdb mydb -U ec2-user
作られたことを確認
$ psql -l データベース一覧 名前 | 所有者 | エンコーディング | 照合順序 | Ctype(変換演算子) | アクセス権 -----------+----------+------------------+-------------+-------------------+----------------------- mydb | ec2-user | UTF8 | en_US.UTF-8 | en_US.UTF-8 | postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres + | | | | | postgres=CTc/postgres template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres + | | | | | postgres=CTc/postgres (4 行)
DBに接続
$ psql mydb
ここのチュートリアルを参考に、テーブルを作成してみる
CREATE TABLE weather ( city varchar(80), temp_lo int, -- 最低気温 temp_hi int, -- 最高気温 prcp real, -- 降水量 date date );
作られたことを確認
mydb=> \d リレーションの一覧 スキーマ | 名前 | 型 | 所有者 ----------+---------+----------+---------- public | weather | テーブル | ec2-user (1 行)
行を挿入
INSERT INTO weather VALUES ('San Francisco', 46, 50, 0.25, '1994-11-27');
挿入されたことを確認
mydb=> select * from weather; city | temp_lo | temp_hi | prcp | date ---------------+---------+---------+------+------------ San Francisco | 46 | 50 | 0.25 | 1994-11-27 (1 行)
今日はここまで
自分が知らなかったことや興味があったことだけをメモしているので、全体が知りたい人は WEB+DB PRESS を買って読みましょう
9系までは、x.y.z の x.y がメジャーバージョン(9.6.5 ならば、9.6がメジャーバージョン)
10系からは、x.y の x がメジャーバージョン(10.1 ならば、10がメジャーバージョン)
2017年からは、2Q末にメジャーバージョンが毎年リリースされている
最新のメジャーバージョンはPostgreSQL11で、12が開発中
なお、各メジャーバージョンのサポート期限は4世代(4年)
ロケールのデフォルトは環境の言語に依存するので、依存しないように C にするのが一般的
文字コードはデフォルトは sql_ascii なので、UTF-8にしておくのが無難
パスワードと、IPアドレスによるアクセス制限をしっかりつけておく
PostgreSQLはマルチプロセス(MySQLはマルチスレッド)
いろいろなプロセスが、それぞれの役割をこなしている
など
基本的にはメモリ内(共有バッファ)上で、データを更新する
そして、ライタプロセスが、 チェックポイント と呼ばれる特定のタイミングで、メモリの内容をストレージに書き込む
それとは別に、WALライタが、共有バッファの更新毎に、差分をWALファイルに書き込んでいる
サーバがクラッシュした時には、 チェックポイントとメモリの差分はWALファイルに格納されているので、それを使ってリカバリを行う
共有メモリ と プロセスメモリ の2種類がある
PostgreSQL全体で使用するメモリ
バックエンドプロセス毎に持つメモリ
(OSのメモリ - 共有バッファのサイズ)/max_connection
を超えない範囲でチューニングしていく必要があるPostgreSQLのデータの更新は、参照を置き換えるという形
参照を置き換えた結果、使用されなくなったデータファイルは VACUUM という仕組みを使って再利用される
なお、PostgreSQLでは データを削除してもデータファイルの合計サイズは減らない
CLUSTER
コマンドが適切らしいpg_repack
というツールもあるpg_dump
pg_basebackup
pg_rman
は、上記のバックアップ&リストアを簡単に行えるツールストリーミングレプリケーションと、ロジカルレプリケーションがある
積極的に対応するべき
PostgreSQLの再起動が必要だが、ストリーミングレプリケーションを使って、スタンバイから更新すれば難しいことはないはず
ストリーミングレプリケーションは使えない
データファイルやWALに互換性がないこともあるため、物理バックアップからの復旧もできない
pg_dump
の結果を新バージョンのDBに反映させるのが一番スタンダード
現在のサーバで pg_upgrade
するほうが、停止時間は短い
[改訂新版]内部構造から学ぶPostgreSQL 設計・運用計画の鉄則 (Software Design plus)
記事だけよんでわからなかった部分を調べた時に読んだページ
www.slideshare.net