TechHub

エンジニアの成長をサポートする技術情報サイト

← 記事一覧に戻る

データベースのレプリケーションとは?高可用性とスケーラビリティ

公開日: 2024年2月24日 著者: mogura
データベースのレプリケーションとは?高可用性とスケーラビリティ

疑問

データベースのレプリケーションとは何で、どのように高可用性とスケーラビリティを実現するのでしょうか?マスター・スレーブ構成について一緒に学んでいきましょう。

導入

データベースのレプリケーションは、複数のサーバーにデータを複製することで、高可用性とスケーラビリティを実現する技術です。マスターサーバーで書き込みを行い、スレーブサーバーで読み取りを行うことで、負荷を分散できます。

本記事では、レプリケーションの基本概念から、マスター・スレーブ構成、レプリケーション遅延の対策、フェイルオーバーの実装まで、詳しく解説していきます。

レプリケーションのイメージ

解説

1. レプリケーションとは

レプリケーションは、1つのデータベースサーバー(マスター)のデータを、他のサーバー(スレーブ)に複製する技術です。高可用性、スケーラビリティ、バックアップ、地理的分散などのメリットがあります。

レプリケーションのメリット

  • 高可用性: マスターが障害発生時、スレーブに切り替えることで、サービスを継続できます。自動フェイルオーバーを実装することで、ダウンタイムを最小限に抑えられます。
  • スケーラビリティ: 読み取り負荷をスレーブに分散することで、システム全体のパフォーマンスを向上させることができます。複数のスレーブを配置することで、読み取り負荷をさらに分散できます。
  • バックアップ: スレーブをバックアップとして使用できます。スレーブでバックアップを取得することで、マスターへの負荷を減らすことができます。
  • 地理的分散: 異なる地域にスレーブを配置することで、ユーザーに近いサーバーからデータを提供でき、レイテンシを削減できます。
  • 読み取り専用クエリの分離: レポート生成や分析クエリなどの重い読み取りクエリをスレーブで実行することで、マスターの負荷を減らすことができます。

レプリケーションの種類

マスター・スレーブレプリケーションは、1つのマスターと複数のスレーブで構成されます。マスター・マスターレプリケーションは、複数のマスターが相互にレプリケーションを行います。また、同期レプリケーションと非同期レプリケーションがあり、同期レプリケーションはデータの整合性が高いですが、パフォーマンスに影響を与える可能性があります。

レプリケーションの仕組み

マスターサーバーは、データの変更をバイナリログ(MySQL)やWAL(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/data

MHAを使用した自動フェイルオーバー

この例では、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

# マスターが障害発生時、自動的にスレーブをマスターに昇格

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

8. ベストプラクティス

データベースのレプリケーションを効率的に運用するためには、いくつかのベストプラクティスに従うことが重要です。適切な監視、定期的なテスト、セキュリティ対策など、実践的なアドバイスを提供します。

  • 定期的な監視: レプリケーションの状態を定期的に監視し、遅延やエラーがないか確認します。自動監視ツールを使用して、問題を早期に発見します。
  • フェイルオーバーテスト: 定期的にフェイルオーバーテストを実施し、手順を確認します。実際の障害時に迅速に対応できるよう、手順を文書化し、訓練を実施します。
  • スレーブのスペック: スレーブサーバーのスペックをマスターと同等以上にします。これにより、レプリケーション遅延を最小限に抑えられます。
  • ネットワークの最適化: マスターとスレーブを同じデータセンター内に配置し、ネットワーク遅延を最小限に抑えます。地理的に離れた場所に配置する場合は、専用回線の使用を検討します。
  • セキュリティ対策: レプリケーション接続を暗号化し、適切な認証を実施します。レプリケーション用ユーザーには最小限の権限のみを付与します。
  • バックアップ戦略: スレーブをバックアップに使用することで、マスターへの負荷を減らします。複数のスレーブを配置し、バックアップ専用のスレーブを作成することも検討します。
  • 読み取り負荷の分散: 読み取りクエリをスレーブに分散することで、マスターの負荷を減らします。ロードバランサーを使用して、読み取りクエリを自動的に分散します。
  • レプリケーション遅延の許容範囲: アプリケーションの要件に応じて、レプリケーション遅延の許容範囲を定義します。リアルタイム性が重要な場合は、同期レプリケーションを検討します。
  • ドキュメント化: レプリケーション構成、フェイルオーバー手順、トラブルシューティング手順などを文書化します。これにより、担当者が変更になっても対応できます。
  • 定期的なメンテナンス: 定期的にレプリケーションの状態を確認し、必要に応じてメンテナンスを実施します。古いバイナリログやWALファイルを削除し、ディスク容量を管理します。

まとめ

データベースのレプリケーションは、高可用性とスケーラビリティを実現するための重要な技術です。マスター・スレーブ構成により、読み取り負荷を分散し、マスターの障害時にはスレーブに切り替えることができます。

レプリケーション遅延の対策、適切なモニタリング、フェイルオーバーの実装など、様々な要素を考慮することで、より堅牢なデータベースシステムを構築できます。クラウド環境では、マネージドサービスのレプリケーション機能を活用することで、簡単にレプリケーションを設定できます。

実践的なプロジェクトでレプリケーションを実装し、経験を積むことで、より可用性の高いシステムを構築できるようになります。

データベースのセキュリティ対策とは?アクセス制御と暗号化 データベースのパフォーマンスチューニングとは?クエリ最適化の実践