疑問
データベースのレプリケーションとは何で、どのように高可用性とスケーラビリティを実現するのでしょうか?マスター・スレーブ構成について一緒に学んでいきましょう。
導入
データベースのレプリケーションは、複数のサーバーにデータを複製することで、高可用性とスケーラビリティを実現する技術です。マスターサーバーで書き込みを行い、スレーブサーバーで読み取りを行うことで、負荷を分散できます。
本記事では、レプリケーションの基本概念から、マスター・スレーブ構成、レプリケーション遅延の対策、フェイルオーバーの実装まで、詳しく解説していきます。
解説
1. レプリケーションとは
レプリケーションは、1つのデータベースサーバー(マスター)のデータを、他のサーバー(スレーブ)に複製する技術です。高可用性、スケーラビリティ、バックアップ、地理的分散などのメリットがあります。
レプリケーションのメリット
- 高可用性: マスターが障害発生時、スレーブに切り替えることで、サービスを継続できます。自動フェイルオーバーを実装することで、ダウンタイムを最小限に抑えられます。
- スケーラビリティ: 読み取り負荷をスレーブに分散することで、システム全体のパフォーマンスを向上させることができます。複数のスレーブを配置することで、読み取り負荷をさらに分散できます。
- バックアップ: スレーブをバックアップとして使用できます。スレーブでバックアップを取得することで、マスターへの負荷を減らすことができます。
- 地理的分散: 異なる地域にスレーブを配置することで、ユーザーに近いサーバーからデータを提供でき、レイテンシを削減できます。
- 読み取り専用クエリの分離: レポート生成や分析クエリなどの重い読み取りクエリをスレーブで実行することで、マスターの負荷を減らすことができます。
レプリケーションの種類
マスター・スレーブレプリケーションは、1つのマスターと複数のスレーブで構成されます。マスター・マスターレプリケーションは、複数のマスターが相互にレプリケーションを行います。また、同期レプリケーションと非同期レプリケーションがあり、同期レプリケーションはデータの整合性が高いですが、パフォーマンスに影響を与える可能性があります。
レプリケーションの仕組み
マスターサーバーは、データの変更をバイナリログ(MySQL)やWAL(PostgreSQL)に記録します。スレーブサーバーは、これらのログを読み取り、同じ変更を適用します。これにより、マスターとスレーブのデータが同期されます。
参考リンク: MySQL Replication - MySQLのレプリケーションに関する詳細なドキュメント
参考リンク: PostgreSQL Replication - PostgreSQLのレプリケーションと高可用性に関するドキュメント
2. マスター・スレーブ構成
マスター・スレーブ構成は、最も一般的なレプリケーション構成です。マスターサーバーで書き込みを行い、スレーブサーバーで読み取りを行うことで、負荷を分散できます。
マスターサーバーの設定
MySQLでは、my.cnfでserver-idとlog-binを設定し、バイナリログを有効化します。PostgreSQLでは、postgresql.confでwal_levelをreplicaに設定し、pg_hba.confでレプリケーション接続を許可します。レプリケーション用の専用ユーザーを作成し、適切な権限を付与します。
スレーブサーバーの設定
MySQLでは、CHANGE MASTERコマンドでマスターの情報を設定し、START SLAVEでレプリケーションを開始します。PostgreSQLでは、pg_basebackupでベースバックアップを取得し、recovery.confでマスターの情報を設定します。
レプリケーションの確認
MySQLでは、SHOW SLAVE STATUSコマンドでレプリケーションの状態を確認できます。PostgreSQLでは、pg_stat_replicationビューでレプリケーションの状態を確認できます。レプリケーション遅延やエラーがないか定期的に確認することが重要です。
MySQL: マスター・スレーブレプリケーション
この例では、MySQLでマスター・スレーブレプリケーションを設定する手順を示しています。マスター側でレプリケーション用ユーザーを作成し、スレーブ側でCHANGE MASTERコマンドを実行します。
-- MySQL: マスター・スレーブレプリケーションの設定
-- マスター側の設定(my.cnf)
-- [mysqld]
-- server-id = 1
-- log-bin = mysql-bin
-- binlog-format = ROW
-- レプリケーション用ユーザーの作成
CREATE USER 'repl'@'%' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;
-- マスターの状態を確認
SHOW MASTER STATUS;
-- 出力例:
-- File: mysql-bin.000001
-- Position: 154
-- スレーブ側の設定
CHANGE MASTER TO
MASTER_HOST='master.example.com',
MASTER_USER='repl',
MASTER_PASSWORD='password',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=154;
-- レプリケーションの開始
START SLAVE;
-- レプリケーションの状態を確認
SHOW SLAVE STATUS\G
-- 重要な列:
-- Slave_IO_Running: Yes(I/Oスレッドが実行中)
-- Slave_SQL_Running: Yes(SQLスレッドが実行中)
-- Seconds_Behind_Master: 0(遅延なし)PostgreSQL: マスター・スレーブレプリケーション
この例では、PostgreSQLでマスター・スレーブレプリケーションを設定する手順を示しています。WALアーカイブを有効にし、pg_basebackupでベースバックアップを取得します。
# PostgreSQL: マスター・スレーブレプリケーションの設定
# マスター側の設定(postgresql.conf)
# wal_level = replica
# max_wal_senders = 3
# archive_mode = on
# archive_command = 'cp %p /backup/wal/%f'
# レプリケーション用ユーザーの作成
psql -U postgres -c "CREATE USER repl WITH REPLICATION PASSWORD 'password';"
# pg_hba.confに追加
# host replication repl 0.0.0.0/0 md5
# スレーブ側の設定
# 1. ベースバックアップの取得
pg_basebackup -h master.example.com -D /var/lib/postgresql/data -U repl -P -W
# 2. recovery.confの作成(PostgreSQL 12以降はpostgresql.auto.conf)
cat > /var/lib/postgresql/data/recovery.conf << EOF
standby_mode = 'on'
primary_conninfo = 'host=master.example.com port=5432 user=repl password=password'
trigger_file = '/tmp/postgresql.trigger'
EOF
# 3. PostgreSQLの起動(自動的にスタンバイモードで起動)
systemctl start postgresql
# レプリケーションの状態を確認
psql -U postgres -c "SELECT * FROM pg_stat_replication;"3. レプリケーション遅延の対策
レプリケーション遅延は、マスターとスレーブの間でデータの同期が遅れる現象です。ネットワーク遅延、スレーブの負荷、大きなトランザクションなどが原因となります。適切な対策を実施することで、遅延を最小限に抑えられます。
遅延の原因
- ネットワーク遅延: マスターとスレーブの間のネットワーク遅延が大きい場合、レプリケーションが遅れます。地理的に離れた場所にスレーブを配置する場合に発生しやすいです。
- スレーブの負荷: スレーブサーバーのCPUやI/Oが高い負荷にある場合、レプリケーションの処理が遅れます。読み取りクエリが多すぎる場合に発生しやすいです。
- 大きなトランザクション: 大量のデータを更新するトランザクションは、レプリケーションに時間がかかります。バッチ処理などで大量のデータを更新する場合に発生しやすいです。
- スレーブのスペック不足: スレーブサーバーのスペックがマスターより低い場合、レプリケーションが遅れます。マスターと同等以上のスペックを推奨します。
対策
ネットワーク遅延を減らすため、マスターとスレーブを同じデータセンター内に配置します。スレーブの負荷を減らすため、読み取りクエリを分散し、適切なインデックスを作成します。大きなトランザクションを避けるため、小さなトランザクションに分割します。スレーブのスペックをマスターと同等以上にします。
並列レプリケーション(MySQL 5.7+)
MySQL 5.7以降では、並列レプリケーション機能が利用できます。複数のスレッドでレプリケーションを実行することで、レプリケーションの速度を向上させることができます。slave_parallel_workersを設定することで、並列ワーカーの数を指定できます。
レプリケーション遅延の監視
MySQLでは、SHOW SLAVE STATUSのSeconds_Behind_Masterで遅延を確認できます。PostgreSQLでは、pg_stat_replicationのlagで遅延を確認できます。遅延が大きい場合は、アラートを送信し、原因を調査します。
MySQL: レプリケーション遅延の確認と対策
この例では、MySQLでレプリケーション遅延を確認し、並列レプリケーションを設定しています。
-- MySQL: レプリケーション遅延の確認
SHOW SLAVE STATUS\G
-- 重要な列:
-- Seconds_Behind_Master: 遅延秒数(0が理想)
-- Slave_IO_Running: I/Oスレッドの状態
-- Slave_SQL_Running: SQLスレッドの状態
-- Last_IO_Error: I/Oエラー
-- Last_SQL_Error: SQLエラー
-- 並列レプリケーションの設定
SET GLOBAL slave_parallel_workers = 4;
SET GLOBAL slave_parallel_type = 'LOGICAL_CLOCK';
-- レプリケーションの一時停止(メンテナンス時)
STOP SLAVE;
-- レプリケーションの再開
START SLAVE;PostgreSQL: レプリケーション遅延の確認
この例では、PostgreSQLでレプリケーション遅延を確認しています。lag_bytesとlag_secondsで遅延を確認できます。
-- PostgreSQL: レプリケーション遅延の確認
SELECT
client_addr,
state,
sync_state,
pg_wal_lsn_diff(pg_current_wal_lsn(), sent_lsn) AS lag_bytes,
EXTRACT(EPOCH FROM (now() - sent_time)) AS lag_seconds
FROM pg_stat_replication;
-- レプリケーションの一時停止(メンテナンス時)
-- recovery.confでpause_at_recovery_targetを設定4. マスター・マスターレプリケーション
マスター・マスターレプリケーションは、複数のマスターサーバーが相互にレプリケーションを行う構成です。書き込みの負荷分散が可能ですが、競合解決が必要になる場合があります。
双方向レプリケーション
マスター・マスターレプリケーションでは、両方のサーバーがマスターとして機能し、相互にレプリケーションを行います。これにより、どちらのサーバーからも書き込みが可能になります。ただし、同じデータを同時に更新すると競合が発生する可能性があるため、アプリケーション側で適切に制御する必要があります。
使用ケース
マスター・マスターレプリケーションは、地理的に離れた場所にサーバーを配置し、それぞれの地域からの書き込みを処理する場合に有効です。また、一方のサーバーが障害発生時にも、もう一方のサーバーで書き込みを継続できるため、高可用性を向上させることができます。
注意点
マスター・マスターレプリケーションでは、競合解決が必要になります。同じデータを同時に更新すると、どちらの変更が優先されるかが不明確になります。また、レプリケーションループを防ぐため、auto_increment_incrementやauto_increment_offsetを適切に設定する必要があります。
MySQL: マスター・マスターレプリケーション
この例では、MySQLでマスター・マスターレプリケーションを設定しています。auto_increment_incrementとauto_increment_offsetを設定することで、IDの競合を防ぎます。
-- MySQL: マスター・マスターレプリケーションの設定
-- サーバー1の設定(my.cnf)
-- [mysqld]
-- server-id = 1
-- log-bin = mysql-bin
-- auto_increment_increment = 2
-- auto_increment_offset = 1
-- サーバー2の設定(my.cnf)
-- [mysqld]
-- server-id = 2
-- log-bin = mysql-bin
-- auto_increment_increment = 2
-- auto_increment_offset = 2
-- サーバー1でサーバー2をスレーブとして設定
CHANGE MASTER TO
MASTER_HOST='server2.example.com',
MASTER_USER='repl',
MASTER_PASSWORD='password',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=154;
START SLAVE;
-- サーバー2でサーバー1をスレーブとして設定
CHANGE MASTER TO
MASTER_HOST='server1.example.com',
MASTER_USER='repl',
MASTER_PASSWORD='password',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=154;
START SLAVE;5. レプリケーションのモニタリング
レプリケーションの状態を定期的に監視することで、問題を早期に発見し、迅速に対応できます。レプリケーション遅延、エラー、パフォーマンスなどを監視します。
レプリケーション状態の確認
MySQLでは、SHOW SLAVE STATUSコマンドでレプリケーションの状態を確認できます。PostgreSQLでは、pg_stat_replicationビューでレプリケーションの状態を確認できます。レプリケーションが正常に動作しているか、遅延がないか、エラーが発生していないかを確認します。
アラートの設定
レプリケーション遅延が一定時間以上続く場合、レプリケーションが停止した場合、エラーが発生した場合などに、アラートを送信します。監視ツール(Prometheus、Nagiosなど)を使用して、自動的にアラートを送信することができます。
パフォーマンスの監視
レプリケーションの処理速度、ネットワーク転送量、スレーブの負荷などを監視します。これにより、ボトルネックを特定し、最適化することができます。
レプリケーション監視スクリプト
この例では、レプリケーションの状態を監視し、遅延が大きい場合にアラートを送信するスクリプトを示しています。
#!/bin/bash
# レプリケーション監視スクリプトの例
# MySQL: レプリケーション状態の確認
mysql -u root -p -e "SHOW SLAVE STATUS\G" | grep -E "Slave_IO_Running|Slave_SQL_Running|Seconds_Behind_Master|Last_IO_Error|Last_SQL_Error"
# レプリケーション遅延が60秒以上の場合、アラートを送信
LAG=$(mysql -u root -p -e "SHOW SLAVE STATUS\G" | grep "Seconds_Behind_Master" | awk '{print $2}')
if [ "$LAG" -gt 60 ]; then
echo "警告: レプリケーション遅延が${LAG}秒です" | mail -s "レプリケーション遅延アラート" admin@example.com
fi
# PostgreSQL: レプリケーション状態の確認
psql -U postgres -c "SELECT * FROM pg_stat_replication;"6. フェイルオーバー
フェイルオーバーは、マスターサーバーが障害発生時、スレーブサーバーをマスターに昇格させることで、サービスを継続する技術です。自動フェイルオーバーを実装することで、ダウンタイムを最小限に抑えられます。
手動フェイルオーバー
手動フェイルオーバーでは、管理者が手動でスレーブをマスターに昇格させます。MySQLでは、STOP SLAVEとRESET MASTERを実行し、アプリケーションの接続先を変更します。PostgreSQLでは、recovery.confを削除し、pg_ctl promoteを実行します。
自動フェイルオーバー
自動フェイルオーバーでは、マスターサーバーの障害を検知し、自動的にスレーブをマスターに昇格させます。MHA(Master High Availability)、Pacemaker、Patroniなどのツールを使用して実装できます。これにより、ダウンタイムを最小限に抑えられます。
フェイルオーバーの手順
フェイルオーバーを実行する際は、まずスレーブのレプリケーションを停止し、マスターに昇格させます。その後、アプリケーションの接続先を変更します。元のマスターが復旧した場合は、新しいマスターのスレーブとして設定し直します。
スプリットブレインの防止
スプリットブレインは、複数のマスターが同時に存在する状態です。これを防ぐため、クォーラム(過半数のサーバーが正常であることを確認)やVIP(Virtual IP)を使用します。これにより、同時に1つのマスターのみが存在することを保証できます。
手動フェイルオーバーの手順
この例では、MySQLとPostgreSQLで手動フェイルオーバーを実行する手順を示しています。
# MySQL: 手動フェイルオーバー
# 1. スレーブでレプリケーションを停止
STOP SLAVE;
# 2. スレーブをマスターに昇格
RESET MASTER;
# 3. アプリケーションの接続先を変更
# 設定ファイルやロードバランサーの設定を変更
# PostgreSQL: 手動フェイルオーバー
# 1. recovery.confを削除(PostgreSQL 12以降はpostgresql.auto.conf)
rm /var/lib/postgresql/data/recovery.conf
# 2. PostgreSQLを再起動(自動的にマスターとして起動)
systemctl restart postgresql
# または、pg_ctl promoteを使用
pg_ctl promote -D /var/lib/postgresql/dataMHAを使用した自動フェイルオーバー
この例では、MHAを使用した自動フェイルオーバーの設定を示しています。MHAは、マスターの障害を検知し、自動的にスレーブをマスターに昇格させます。
# MHA(Master High Availability)を使用した自動フェイルオーバー
# masterha_check_ssh: SSH接続の確認
masterha_check_ssh --conf=/etc/masterha/app1.cnf
# masterha_check_repl: レプリケーション状態の確認
masterha_check_repl --conf=/etc/masterha/app1.cnf
# masterha_manager: マスター監視の開始
masterha_manager --conf=/etc/masterha/app1.cnf
# マスターが障害発生時、自動的にスレーブをマスターに昇格参考リンク: MHA (Master High Availability) - MySQLの自動フェイルオーバーツールMHAの公式リポジトリ
参考リンク: Patroni - PostgreSQLの高可用性ソリューションPatroniのドキュメント
7. クラウド環境でのレプリケーション
クラウド環境では、マネージドサービスのレプリケーション機能を活用することで、簡単にレプリケーションを設定できます。AWS RDS、Azure Database、Google Cloud SQLなどのサービスでは、自動レプリケーション機能が提供されています。
AWS RDSのレプリケーション
AWS RDSでは、マスターインスタンスから読み取りレプリカを作成できます。読み取りレプリカは、自動的にレプリケーションされ、読み取り負荷を分散できます。マルチAZ構成により、高可用性も実現できます。
Azure Databaseのレプリケーション
Azure Database for MySQLやPostgreSQLでは、読み取りレプリカを作成できます。読み取りレプリカは、異なるリージョンに配置することもでき、地理的分散も実現できます。
Google Cloud SQLのレプリケーション
Google Cloud SQLでは、読み取りレプリカを作成できます。読み取りレプリカは、自動的にレプリケーションされ、読み取り負荷を分散できます。また、フェイルオーバーレプリカを作成することで、高可用性も実現できます。
クラウド環境での読み取りレプリカの作成
これらの例では、AWS RDS、Azure Database、Google Cloud SQLで読み取りレプリカを作成する方法を示しています。
# AWS RDS: 読み取りレプリカの作成
aws rds create-db-instance-read-replica \
--db-instance-identifier mydb-read-replica \
--source-db-instance-identifier mydb-master \
--db-instance-class db.t3.medium
# 読み取りレプリカの確認
aws rds describe-db-instances --db-instance-identifier mydb-read-replica
# Azure Database: 読み取りレプリカの作成
az mysql flexible-server replica create \
--resource-group myResourceGroup \
--name mydb-read-replica \
--source-server mydb-master
# Google Cloud SQL: 読み取りレプリカの作成
gcloud sql instances create mydb-read-replica \
--master-instance-name=mydb-master \
--tier=db-n1-standard-1参考リンク: AWS RDS Read Replicas - AWS RDSの読み取りレプリカに関するドキュメント
8. ベストプラクティス
データベースのレプリケーションを効率的に運用するためには、いくつかのベストプラクティスに従うことが重要です。適切な監視、定期的なテスト、セキュリティ対策など、実践的なアドバイスを提供します。
- 定期的な監視: レプリケーションの状態を定期的に監視し、遅延やエラーがないか確認します。自動監視ツールを使用して、問題を早期に発見します。
- フェイルオーバーテスト: 定期的にフェイルオーバーテストを実施し、手順を確認します。実際の障害時に迅速に対応できるよう、手順を文書化し、訓練を実施します。
- スレーブのスペック: スレーブサーバーのスペックをマスターと同等以上にします。これにより、レプリケーション遅延を最小限に抑えられます。
- ネットワークの最適化: マスターとスレーブを同じデータセンター内に配置し、ネットワーク遅延を最小限に抑えます。地理的に離れた場所に配置する場合は、専用回線の使用を検討します。
- セキュリティ対策: レプリケーション接続を暗号化し、適切な認証を実施します。レプリケーション用ユーザーには最小限の権限のみを付与します。
- バックアップ戦略: スレーブをバックアップに使用することで、マスターへの負荷を減らします。複数のスレーブを配置し、バックアップ専用のスレーブを作成することも検討します。
- 読み取り負荷の分散: 読み取りクエリをスレーブに分散することで、マスターの負荷を減らします。ロードバランサーを使用して、読み取りクエリを自動的に分散します。
- レプリケーション遅延の許容範囲: アプリケーションの要件に応じて、レプリケーション遅延の許容範囲を定義します。リアルタイム性が重要な場合は、同期レプリケーションを検討します。
- ドキュメント化: レプリケーション構成、フェイルオーバー手順、トラブルシューティング手順などを文書化します。これにより、担当者が変更になっても対応できます。
- 定期的なメンテナンス: 定期的にレプリケーションの状態を確認し、必要に応じてメンテナンスを実施します。古いバイナリログやWALファイルを削除し、ディスク容量を管理します。
まとめ
データベースのレプリケーションは、高可用性とスケーラビリティを実現するための重要な技術です。マスター・スレーブ構成により、読み取り負荷を分散し、マスターの障害時にはスレーブに切り替えることができます。
レプリケーション遅延の対策、適切なモニタリング、フェイルオーバーの実装など、様々な要素を考慮することで、より堅牢なデータベースシステムを構築できます。クラウド環境では、マネージドサービスのレプリケーション機能を活用することで、簡単にレプリケーションを設定できます。
実践的なプロジェクトでレプリケーションを実装し、経験を積むことで、より可用性の高いシステムを構築できるようになります。