こんにちは。よっしーです(^^)
今日は、slimのローカル開発環境でMariaDBのRead Replicaを作成する方法についてご紹介します。
前提
この記事は下記の記事をベースにしています。
背景
MariaDBでRead Replicaを作成する機会がありましたので、その時の方法を共有します。
Read Replicaとは
リードレプリカ(read replica)は、データベースシステムにおいてマスターデータベースからデータを非同期的に複製し、読み取りクエリの処理を行うための複製データベースです。マスターデータベースは主に書き込み操作(INSERT、UPDATE、DELETEなど)を担当し、リードレプリカは主に読み取り操作(SELECTなど)を処理します。
リードレプリカは、マスターデータベースからのデータ変更を非同期的に反映させるため、リアルタイムのデータ同期は保証されません。つまり、マスターデータベースに行われた変更は一定の遅延が発生した後にリードレプリカに反映されます。このため、リードレプリカはリアルタイムのデータを必要としない読み取り操作に使用されることが一般的です。
リードレプリカの主な目的は、読み取り負荷の分散と高可用性の向上です。リードレプリカに読み取りクエリをオフロードすることで、マスターデータベースの負荷を軽減し、システム全体のパフォーマンスを向上させることができます。また、マスターデータベースの障害時には、リードレプリカが自動的に昇格して新たなマスターとなることができるため、システムの可用性と耐障害性を高めることができます。
リードレプリカは、データベースシステムのスケーラビリティ、パフォーマンス、可用性の向上に貢献する重要な要素として利用されます。
修正内容
下記のファイルを更新、もしくは、作成します。下記の各セクションに各ファイルの修正内容を記載しています。
modified: app/compose.yml
new file: app/mariadb/conf.d/master_replica.cnf
new file: app/mariadb/initdb.d/v0.0.3_create_replication_user.sql
new file: app/mariadb_read/Dockerfile
new file: app/mariadb_read/conf.d/read_replica.cnf
new file: app/mariadb_read/initdb.d/v0.0.1_start_slave.sh
app/compose.yml
72行目に追加します。
volumes:
+ - "./mariadb/conf.d:/etc/mysql/conf.d"
- "./mariadb/initdb.d:/docker-entrypoint-initdb.d"
80行目に追加します。
+ mariadb_read:
+ build: ./mariadb_read
+ container_name: mariadb_read
+ restart: unless-stopped
+ volumes:
+ - "./mariadb_read/conf.d:/etc/mysql/conf.d"
+ - "./mariadb_read/initdb.d:/docker-entrypoint-initdb.d"
+ environment:
+ - MARIADB_ROOT_PASSWORD=${MARIADB_ROOT_PASSWORD}
+ ports:
+ - 3307:3306
+ depends_on:
+ - mariadb
+ networks:
+ - net
app/mariadb/conf.d/master_replica.cnf
下記の内容で新規作成します。
[mariadb]
log-bin
server-id=1
log-basename=master1
binlog-format=mixed
app/mariadb/initdb.d/v0.0.3_create_replication_user.sql
下記の内容で新規作成します。
CREATE USER 'replication_user'@'%' IDENTIFIED BY 'P@ssw0rd';
GRANT REPLICATION SLAVE ON *.* TO 'replication_user'@'%';
app/mariadb_read/Dockerfile
下記の内容で新規作成します。
FROM mariadb:11.0.2
app/mariadb_read/conf.d/read_replica.cnf
下記の内容で新規作成します。
[mysqld]
log-bin
server-id=2
log-basename=read2
app/mariadb_read/initdb.d/v0.0.1_start_slave.sh
下記の内容で新規作成します。
#!/bin/bash
until mariadb-admin ping -hmariadb -uroot -p${MARIADB_ROOT_PASSWORD} --silent; do
sleep 1
done
mariadb -uroot -p${MARIADB_ROOT_PASSWORD} -e" \
SET GLOBAL gtid_slave_pos = '';
CHANGE MASTER TO \
master_host='mariadb', \
master_port=3306, \
master_user='replication_user', \
master_password='P@ssw0rd', \
master_use_gtid=current_pos;
START SLAVE;
SHOW SLAVE STATUS\G
"
新規作成後、下記のコマンドで実行権限を付与しておきます。
chmod +x app/mariadb_read/initdb.d/v0.0.1_start_slave.sh
動作確認
下記のコマンドを実行します。
make build
make up
下記のコマンドを実行します。
pushd app && docker compose exec mariadb_read mariadb -uroot -p -Dsample -e "show tables;" && popd
下記のような結果になると思います(テーブルが空の想定)。
% pushd app && docker compose exec mariadb_read mariadb -uroot -p -Dsample -e "show tables;" && popd
~/github/Ran/app ~/github/Ran ~/github/Ran
Enter password: [パスワード入力]
~/github/Ran ~/github/Ran
下記のコマンドを実行します。
make migrate_up
下記のコマンドを実行します。
pushd app && docker compose exec mariadb_read mariadb -uroot -p -Dsample -e "show tables;" && popd
下記のようにテーブルが表示されていれば成功です。
% pushd app && docker compose exec mariadb_read mariadb -uroot -p -Dsample -e "show tables;" && popd
~/github/Ran/app ~/github/Ran ~/github/Ran
Enter password: [パスワード入力]
+-------------------+
| Tables_in_sample |
+-------------------+
| sample |
| schema_migrations |
+-------------------+
~/github/Ran ~/github/Ran
下記のようにテーブルのデータも確認できると思います。
% pushd app && docker compose exec mariadb_read mariadb -uroot -p -Dsample -e "select * from sample;" && popd
~/github/Ran/app ~/github/Ran ~/github/Ran
Enter password:
+----+--------+---------------------+
| id | title | created_at |
+----+--------+---------------------+
| 1 | test 1 | 2023-07-17 04:09:20 |
+----+--------+---------------------+
~/github/Ran ~/github/Ran
解説
app/compose.yml
このコードは、Dockerを使用してMariaDBのリードレプリカを構築するための設定を示しています。以下にコードの要点を解説します。
mariadb_read
:build: ./mariadb_read
:mariadb_read
というサービスのDockerイメージをビルドするためのDockerfileのパスを指定しています。./mariadb_read
は、現在のディレクトリからの相対パスを意味します。container_name: mariadb_read
: コンテナの名前をmariadb_read
と指定しています。restart: unless-stopped
: コンテナが停止した場合に自動的に再起動するように設定しています。
volumes
:./mariadb_read/conf.d:/etc/mysql/conf.d
:./mariadb_read/conf.d
ディレクトリをコンテナ内の/etc/mysql/conf.d
ディレクトリにマウントしています。ここにはMariaDBの設定ファイルが含まれています。./mariadb_read/initdb.d:/docker-entrypoint-initdb.d
:./mariadb_read/initdb.d
ディレクトリをコンテナ内の/docker-entrypoint-initdb.d
ディレクトリにマウントしています。ここには初期化スクリプトが含まれており、データベースの初期化時に実行されます。
environment
:MARIADB_ROOT_PASSWORD=${MARIADB_ROOT_PASSWORD}
: MariaDBのルートユーザーのパスワードを環境変数から取得しています。${MARIADB_ROOT_PASSWORD}
は、事前に設定された環境変数の値を参照しています。
ports
:3307:3306
: コンテナのポート3306をホストのポート3307にマッピングしています。これにより、ホストマシンからlocalhost:3307
を介してコンテナ内のMariaDBにアクセスできるようになります。
depends_on
:- mariadb
:mariadb_read
サービスがmariadb
サービスに依存していることを示しています。つまり、mariadb
サービスが起動していないと、mariadb_read
サービスは起動しません。
networks
:- net
:net
という名前のDockerネットワークにmariadb_read
コンテナを接続します。このネットワークを介して他のサービスとの通信が可能になります。
このコードは、マスターノードとなるMariaDBのコンテナ(mariadb
)に依存し、そのデータを非同期に複製するリードレプリカとしてのMariaDBのコンテナ(mariadb_read
)を構築します。設定ファイルや初期化スクリプトがマウントされ、必要なポートがマッピングされています。また、環境変数からルートパスワードが取得されます。
app/mariadb/conf.d/master_replica.cnf
このコードは、MariaDBの設定ファイルであるmy.cnf
(またはmy.ini
)に関する設定を示しています。以下にコードの要点を解説します。
[mariadb]
:[mariadb]
は、この設定がMariaDBに関連していることを示すセクションの名前です。設定ファイル内には他のセクションも存在する可能性があります。
log-bin
:log-bin
は、バイナリログ(binary log)を有効にするための設定です。バイナリログは、データベースの変更操作(INSERT、UPDATE、DELETEなど)が記録されるファイルです。バイナリログはリードレプリカの構築やデータの復元に使用されます。
server-id=1
:server-id
は、MariaDBサーバーの一意の識別子を指定します。複数のサーバーが存在する場合、それぞれのサーバーに一意のserver-id
が必要です。この設定はリードレプリカを構築するために必要であり、マスターノードとリードレプリカを区別するために使用されます。
log-basename=master1
:log-basename
は、バイナリログファイルのベースネーム(基本となる名前)を指定します。バイナリログファイルは、指定されたベースネームに連番が付与されて生成されます。この設定により、生成されるバイナリログファイルの名前が制御されます。
binlog-format=mixed
:binlog-format
は、バイナリログのフォーマットを指定します。この場合、mixed
という値が指定されています。mixed
フォーマットは、ステートメントレプリケーション(SQLステートメントの実行をそのままバイナリログに記録)とロウレプリケーション(変更された行の実際のデータをバイナリログに記録)の両方をサポートしています。
この設定ファイルのセクションでは、バイナリログの有効化とサーバーの識別子の設定、バイナリログファイルのベースネームの指定、そしてバイナリログのフォーマットの設定が行われています。これらの設定はリードレプリカの構築やデータの同期に関連しています。
app/mariadb/initdb.d/v0.0.3_create_replication_user.sql
このSQLは、MariaDBにおいてリードレプリケーションのためのユーザーを作成し、必要な権限を与えるためのコマンドです。以下にコードの要点を解説します。
CREATE USER 'replication_user'@'%' IDENTIFIED BY 'P@ssw0rd';
:CREATE USER
は、新しいユーザーを作成するためのコマンドです。'replication_user'@'%'
は、新しいユーザーの識別子とホストを指定しています。ここではユーザー名がreplication_user
であり、%
(ワイルドカード)を指定することでどのホストからの接続でも許可されることを意味します。IDENTIFIED BY 'P@ssw0rd'
は、ユーザーのパスワードを指定しています。ここではP@ssw0rd
というパスワードを設定しています。
GRANT REPLICATION SLAVE ON *.* TO 'replication_user'@'%';
:GRANT
は、ユーザーに対して権限を付与するためのコマンドです。REPLICATION SLAVE
は、リードレプリケーションに必要なスレーブ権限を指定しています。これにより、replication_user
ユーザーにリードレプリケーションの操作を実行する権限が与えられます。*.*
は、全てのデータベースとテーブルに対する権限を指定しています。TO 'replication_user'@'%'
は、どのユーザーに対して権限を付与するかを指定しています。ここではreplication_user
ユーザーに対して全てのホストからの接続で権限を有効にしています。
このSQLの実行により、replication_user
というユーザーが作成され、リードレプリケーションの操作を実行するための権限が付与されます。このユーザーはリードレプリカの設定に使用され、マスターノードからのバイナリログの受信やデータの同期を行うために必要です。パスワードはP@ssw0rd
として設定されていますが、実際のパスワードはセキュリティ上の理由から強力なものに変更することが推奨されます。
app/mariadb_read/initdb.d/v0.0.1_start_slave.sh
このコードは、Bashスクリプトとして書かれており、MariaDBのリードレプリカを構成するための一連のコマンドを実行しています。以下にコードの要点を解説します。
#!/bin/bash
:- シェルスクリプトを実行するためのシバン(shebang)行です。この行により、スクリプトがBashで実行されることが指定されます。
until mariadb-admin ping -hmariadb -uroot -p${MARIADB_ROOT_PASSWORD} --silent; do sleep 1 done
:mariadb-admin ping
コマンドを使用して、MariaDBサーバーに接続可能かどうかを確認しています。- ループ内で
sleep 1
が実行され、1秒間隔で繰り返し接続を試みます。 - MariaDBサーバーが応答しなくなるまで繰り返し接続を試みるため、これによりリードレプリカがマスターノードに正常に接続できるまで待機します。
mariadb -uroot -p${MARIADB_ROOT_PASSWORD} -e" ... "
:mariadb
コマンドを使用して、MariaDBクライアントを起動し、指定されたSQLコマンドを実行します。-uroot
および-p${MARIADB_ROOT_PASSWORD}
は、MariaDBへのルートユーザーとしての認証情報を指定しています。-e" ... "
の間には、実行するSQLコマンドが記述されています。
SET GLOBAL gtid_slave_pos = '';
:gtid_slave_pos
システム変数を空の文字列に設定しています。これは、リードレプリカのGTID(グローバルトランザクションID)のスレーブ位置をリセットするためのものです。
CHANGE MASTER TO ...
:- マスターノードへの接続設定を行っています。
mariadb
はマスターホスト名、3306
はマスターポート番号、replication_user
はリードレプリケーション用のユーザー名、P@ssw0rd
はユーザーのパスワードを示しています。master_use_gtid=current_pos
は、GTIDを使用してデータの同期を行うために設定しています。
START SLAVE;
:- リードレプリカのスレーブプロセスを開始します。これにより、マスターノードからのバイナリログの受信とデータの同期が開始されます。
SHOW SLAVE STATUS\G
:- リードレプリカのステータス情報を表示します。
\G
は結果を垂直フォーマットで表示するためのオプションです。
- リードレプリカのステータス情報を表示します。
このスクリプトは、リードレプリカがマスターノードに正常に接続できるまで待機し、その後、マスターノードへの接続設定を行いリードレプリカを起動します。最後に、リードレプリカのステータス情報を表示します。
リードレプリカを使用するメリット
MariaDBにおけるリードレプリカ(read replica)の作成にはいくつかの理由があります。以下にその主な理由をいくつか挙げます。
- 読み取り負荷の分散:リードレプリカは、マスターデータベースに対する読み取りクエリの負荷を分散するために使用されます。リードレプリカに読み取りクエリをオフロードすることで、マスターデータベースの負荷を軽減し、スケーラビリティを向上させることができます。
- 高可用性と耐障害性:リードレプリカは、マスターデータベースの障害時に自動的に切り替えるフェールオーバーのメカニズムとして使用できます。マスターデータベースがダウンした場合でも、リードレプリカは引き続き読み取りクエリを処理できるため、アプリケーションの可用性を高めることができます。
- バックアップと復元:リードレプリカは、マスターデータベースのバックアップとしても使用できます。リードレプリカはマスターデータベースと同期しているため、リードレプリカからデータを復元することができます。これにより、データの損失を最小限に抑えることができます。
- リードレプリカでのテストやレポート作成:リードレプリカは、本番環境に影響を与えずにテストやレポート作成を行うための環境としても使用できます。リードレプリカ上でさまざまなクエリや操作を実行し、その結果を検証することができます。
これらの利点により、MariaDBのリードレプリカは、パフォーマンスの向上、可用性の向上、データ保護、テスト環境の提供など、さまざまなシナリオで役立ちます。
おわりに
今日は、slimのローカル開発環境でMariaDBのRead Replicaを作成する方法についてご紹介しました。
ローカルの開発環境では、リードレプリカを作成したことはなかったので、いろいろと勉強になりました。
本記事でご紹介したソースは、下記のリポジトリにあります。
何か質問や相談があれば、遠慮なくコメントしてください。また、エンジニア案件についても、いつでも相談にのっていますので、お気軽にお問い合わせください。
それでは、また明日お会いしましょう(^^)
コメント