ProxySQLは、MySQL、MariaDB、およびClickHouseをサポートするインテリジェントで高性能なSQLプロキシです。最近、ProxySQL 2.0はGAになり、GTID整合性のある読み取り、フロントエンドSSL、Galera、MySQLグループレプリケーションのネイティブサポートなどの新しいエキサイティングな機能が付属しています。
ProxySQLをDockerコンテナとして実行するのは比較的簡単です。以前、KubernetesでProxySQLをヘルパーコンテナとして、またはProxySQL1.xに基づくKubernetesサービスとして実行する方法について説明しました。このブログ投稿では、GaleraCluster構成に異なるアプローチを使用する新しいバージョンのProxySQL2.xを使用します。
ProxySQL2.xDockerイメージ
新しいProxySQL2.0Dockerイメージコンテナをリリースしました。これは、DockerHubで利用できます。 READMEには、v2.xの前後で、特にGaleraおよびMySQLレプリケーションの構成例が多数用意されています。構成行は、テキストファイルで定義し、/ etc / proxysql.cnfにあるコンテナのパスにマップして、ProxySQLサービスにロードできます。
イメージの「最新」タグは、ProxySQL 2.0が正式にGAになるまで1.xを指します(ProxySQLチームからの公式リリースのブログ/記事はまだ見ていません)。つまり、Severeninesの最新のタグを使用してProxySQLイメージをインストールする場合は常に、バージョン1.xを使用できます。新しい構成例では、ProxySQL Web統計(1.4.4で導入されましたが、まだベータ版です)も有効になっていることに注意してください。これは、ProxySQL自体の全体的な構成とステータスを要約したシンプルなダッシュボードです。
GaleraクラスターのProxySQL2.xサポート
GaleraClusterのネイティブサポートについて詳しく説明しましょう。新しいmysql_galera_hostgroupsテーブルは、次のフィールドで構成されています。
- writer_hostgroup : ライターであるすべてのメンバーを含むホストグループのID(read_only =0)。
- backup_writer_hostgroup : クラスタがマルチライターモードで実行されていて(つまり、read_only =0のノードが複数ある場合)、max_writersがノードの総数よりも少ない数に設定されている場合、追加のノードはこのバックアップライターホストグループに移動されます。 >
- reader_hostgroup : リーダーであるすべてのメンバー(つまり、read_only =1を持つノード)を含むホストグループのID
- offset_hostgroup : ProxySQLモニタリングによってホストがオフラインであると判断されると、ホストはoffline_hostgroupに移動されます。
- アクティブ : ホストグループをアクティブ化するためのブール値(0または1)
- max_writers : 前述のように、ライターホストグループで許可されるノードの最大数を制御します。追加のノードはbackup_writer_hostgroupに移動されます。
- writer_is_also_reader : 1の場合、writer_hostgroup内のノードもreader_hostgroupに配置され、読み取りに使用されます。 2に設定すると、backup_writer_hostgroupのノードは、writer_hostgroupのノードではなく、reader_hostgroupに配置されます。
- max_transactions_behind : 失効した読み取りを防ぐためにノードがSHUNNEDされる前に、クラスター内のノードがキューに入れることができる書き込みセットの最大数を決定します(これは、wsrep_local_recv_queue Galera変数を照会することによって決定されます)。
- コメント : ユーザーが定義した任意の目的に使用できるテキストフィールド
表形式のmysql_galera_hostgroupsの構成例を次に示します。
Admin> select * from mysql_galera_hostgroups\G
*************************** 1. row ***************************
writer_hostgroup: 10
backup_writer_hostgroup: 20
reader_hostgroup: 30
offline_hostgroup: 9999
active: 1
max_writers: 1
writer_is_also_reader: 2
max_transactions_behind: 20
comment:
ProxySQLは、次のMySQLステータス/変数を監視することによってGaleraヘルスチェックを実行します。
- read_only -ONの場合、writer_is_also_readerが1でない限り、ProxySQLは定義されたホストをreader_hostgroupにグループ化します。
- wsrep_desync -オンの場合、ProxySQLはノードを使用不可としてマークし、offline_hostgroupに移動します。
- wsrep_reject_queries -この変数がオンの場合、ProxySQLはノードを使用不可としてマークし、offline_hostgroupに移動します(特定のメンテナンス状況で役立ちます)。
- wsrep_sst_donor_rejects_queries -この変数がオンの場合、GaleraノードがSSTドナーとして機能している間、ProxySQLはノードを使用不可としてマークし、offline_hostgroupに移動します。
- wsrep_local_state -このステータスが4以外(4は同期済みを意味します)を返す場合、ProxySQLはノードを使用不可としてマークし、offline_hostgroupに移動します。
- wsrep_local_recv_queue -このステータスがmax_transactions_behindよりも高い場合、ノードは回避されます。
- wsrep_cluster_status -このステータスがプライマリ以外に戻った場合、ProxySQLはノードを使用不可としてマークし、offline_hostgroupに移動します。
そうは言っても、mysql_galera_hostgroupsのこれらの新しいパラメーターをmysql_query_rulesと組み合わせることにより、ProxySQL2.xははるかに多くのGaleraユースケースに適合する柔軟性を備えています。たとえば、クエリルールの宛先ホストグループとしてシングルライター、マルチライター、およびマルチリーダーのホストグループを定義し、ライターの数を制限して、古い読み取り動作をより細かく制御することができます。
>これをProxySQL1.xと比較してください。この場合、ユーザーは、バックエンドのヘルスチェックを実行してデータベースサーバーの状態を更新するために外部スクリプトを呼び出すスケジューラーを明示的に定義する必要がありました。これには、スクリプトのカスタマイズが必要です(ユーザーはProxySQL管理者ユーザー/パスワード/ポートを更新する必要があります)。さらに、ProxySQL管理者インターフェイスに接続するための追加ツール(MySQLクライアント)に依存していました。
ProxySQL1.xのテーブル形式のGaleraヘルスチェックスクリプトスケジューラの構成例を次に示します。
Admin> select * from scheduler\G
*************************** 1. row ***************************
id: 1
active: 1
interval_ms: 2000
filename: /usr/share/proxysql/tools/proxysql_galera_checker.sh
arg1: 10
arg2: 20
arg3: 1
arg4: 1
arg5: /var/lib/proxysql/proxysql_galera_checker.log
comment:
さらに、ProxySQLスケジューラスレッドは任意のスクリプトを独立して実行するため、ヘルスチェックスクリプトの多くのバージョンが利用可能です。 ClusterControlによってデプロイされたすべてのProxySQLインスタンスは、ProxySQLインストーラーパッケージによって提供されるデフォルトのスクリプトを使用します。
ProxySQL 2.xでは、max_writers変数とwriter_is_also_reader変数は、ProxySQLがバックエンドMySQLサーバーを動的にグループ化する方法を決定し、接続分散とクエリルーティングに直接影響します。たとえば、次のMySQLバックエンドサーバーについて考えてみます。
Admin> select hostgroup_id, hostname, status, weight from mysql_servers;
+--------------+--------------+--------+--------+
| hostgroup_id | hostname | status | weight |
+--------------+--------------+--------+--------+
| 10 | DB1 | ONLINE | 1 |
| 10 | DB2 | ONLINE | 1 |
| 10 | DB3 | ONLINE | 1 |
+--------------+--------------+--------+--------+
次のGaleraホストグループの定義と一緒に:
Admin> select * from mysql_galera_hostgroups\G
*************************** 1. row ***************************
writer_hostgroup: 10
backup_writer_hostgroup: 20
reader_hostgroup: 30
offline_hostgroup: 9999
active: 1
max_writers: 1
writer_is_also_reader: 2
max_transactions_behind: 20
comment:
すべてのホストが稼働していることを考慮すると、ProxySQLはほとんどの場合ホストを次のようにグループ化します。
それらを1つずつ見ていきましょう:
構成 | 説明 |
---|---|
writer_is_also_reader =0 |
|
writer_is_also_reader =1 |
|
writer_is_also_reader =2 |
|
この構成では、特定のワークロードに対応するために、ホストグループの宛先をさまざまに選択できます。 「ホットスポット」書き込みは、マルチマスターの競合を減らすために1つのサーバーのみに送信するように構成でき、競合しない書き込みは他のマスターに均等に分散でき、ほとんどの読み取りはすべてのMySQLサーバーまたは非ライターに均等に分散できます。重要な読み取り最新のサーバーに転送でき、分析読み取りをスレーブレプリカに転送できます。
GaleraクラスターのProxySQLデプロイメント
この例では、次の図に示すように、ClusterControlによって3ノードのGaleraクラスターが既にデプロイされていると仮定します。
WordpressアプリケーションはDockerで実行され、Wordpressデータベースはベアメタルサーバーで実行されているGaleraClusterでホストされています。 Wordpressコンテナと一緒にProxySQLコンテナを実行して、Wordpressデータベースクエリルーティングをより適切に制御し、データベースクラスタインフラストラクチャを完全に活用することにしました。読み取り/書き込み比率は約80%〜20%であるため、ProxySQLを次のように構成します。
- すべての書き込みを1つのGaleraノードに転送します(競合が少なく、書き込みに集中します)
- 他の2つのGaleraノードへのすべての読み取りのバランスを取ります(ワークロードの大部分の分散を改善します)
まず、Dockerホスト内にProxySQL構成ファイルを作成して、コンテナーにマップできるようにします。
$ mkdir /root/proxysql-docker
$ vim /root/proxysql-docker/proxysql.cnf
次に、次の行をコピーします(構成行についてはさらに下で説明します):
datadir="/var/lib/proxysql"
admin_variables=
{
admin_credentials="admin:admin"
mysql_ifaces="0.0.0.0:6032"
refresh_interval=2000
web_enabled=true
web_port=6080
stats_credentials="stats:admin"
}
mysql_variables=
{
threads=4
max_connections=2048
default_query_delay=0
default_query_timeout=36000000
have_compress=true
poll_timeout=2000
interfaces="0.0.0.0:6033;/tmp/proxysql.sock"
default_schema="information_schema"
stacksize=1048576
server_version="5.1.30"
connect_timeout_server=10000
monitor_history=60000
monitor_connect_interval=200000
monitor_ping_interval=200000
ping_interval_server_msec=10000
ping_timeout_server=200
commands_stats=true
sessions_sort=true
monitor_username="proxysql"
monitor_password="proxysqlpassword"
monitor_galera_healthcheck_interval=2000
monitor_galera_healthcheck_timeout=800
}
mysql_galera_hostgroups =
(
{
writer_hostgroup=10
backup_writer_hostgroup=20
reader_hostgroup=30
offline_hostgroup=9999
max_writers=1
writer_is_also_reader=1
max_transactions_behind=30
active=1
}
)
mysql_servers =
(
{ address="db1.cluster.local" , port=3306 , hostgroup=10, max_connections=100 },
{ address="db2.cluster.local" , port=3306 , hostgroup=10, max_connections=100 },
{ address="db3.cluster.local" , port=3306 , hostgroup=10, max_connections=100 }
)
mysql_query_rules =
(
{
rule_id=100
active=1
match_pattern="^SELECT .* FOR UPDATE"
destination_hostgroup=10
apply=1
},
{
rule_id=200
active=1
match_pattern="^SELECT .*"
destination_hostgroup=30
apply=1
},
{
rule_id=300
active=1
match_pattern=".*"
destination_hostgroup=10
apply=1
}
)
mysql_users =
(
{ username = "wordpress", password = "passw0rd", default_hostgroup = 10, transaction_persistent = 0, active = 1 },
{ username = "sbtest", password = "passw0rd", default_hostgroup = 10, transaction_persistent = 0, active = 1 }
)
それでは、最も構成のセクションのいくつかを見てみましょう。まず、Galeraホストグループの構成を次のように定義します。
mysql_galera_hostgroups =
(
{
writer_hostgroup=10
backup_writer_hostgroup=20
reader_hostgroup=30
offline_hostgroup=9999
max_writers=1
writer_is_also_reader=1
max_transactions_behind=30
active=1
}
)
ホストグループ10はwriter_hostgroupになり、hostgroup 20はbackup_writerになり、hostgroup30はreaderになります。 max_writersを1に設定して、すべての書き込みを送信するホストグループ10のシングルライターホストグループを作成できるようにします。次に、writer_is_also_readerを1に定義します。これにより、すべてのGaleraノードがリーダーとしても使用され、すべてのノードに均等に分散できるクエリに適しています。 ProxySQLが動作不能のGaleraノードを検出した場合、ホストグループ9999はoffline_hostgroup用に予約されています。
次に、MySQLサーバーをデフォルトでホストグループ10に構成します。
mysql_servers =
(
{ address="db1.cluster.local" , port=3306 , hostgroup=10, max_connections=100 },
{ address="db2.cluster.local" , port=3306 , hostgroup=10, max_connections=100 },
{ address="db3.cluster.local" , port=3306 , hostgroup=10, max_connections=100 }
)
上記の構成では、ProxySQLは以下のようにホストグループを「認識」します。
次に、クエリルールを使用してクエリルーティングを定義します。要件に基づいて、すべての読み取りはライター(ホストグループ20)を除くすべてのGaleraノードに送信され、その他はすべて、単一のライターのホストグループ10に転送されます。
mysql_query_rules =
(
{
rule_id=100
active=1
match_pattern="^SELECT .* FOR UPDATE"
destination_hostgroup=10
apply=1
},
{
rule_id=200
active=1
match_pattern="^SELECT .*"
destination_hostgroup=20
apply=1
},
{
rule_id=300
active=1
match_pattern=".*"
destination_hostgroup=10
apply=1
}
)
最後に、ProxySQLを介して渡されるMySQLユーザーを定義します。
mysql_users =
(
{ username = "wordpress", password = "passw0rd", default_hostgroup = 10, transaction_persistent = 0, active = 1 },
{ username = "sbtest", password = "passw0rd", default_hostgroup = 10, transaction_persistent = 0, active = 1 }
)
transaction_persistentを0に設定して、これらのユーザーからのすべての接続が読み取りおよび書き込みルーティングのクエリルールを尊重するようにします。そうしないと、接続が1つのホストグループにヒットし、負荷分散の目的が損なわれることになります。最初にすべてのMySQLサーバーでこれらのユーザーを作成することを忘れないでください。 ClusterControlユーザーの場合、[管理]->[スキーマとユーザー]機能を使用してこれらのユーザーを作成できます。
これで、コンテナを起動する準備が整いました。 ProxySQLコンテナを起動するときに、ProxySQL構成ファイルをバインドマウントとしてマップします。したがって、実行コマンドは次のようになります。
$ docker run -d \
--name proxysql2 \
--hostname proxysql2 \
--publish 6033:6033 \
--publish 6032:6032 \
--publish 6080:6080 \
--restart=unless-stopped \
-v /root/proxysql/proxysql.cnf:/etc/proxysql.cnf \
severalnines/proxysql:2.0
最後に、ProxySQLコンテナポート6033を指すWordpressデータベースを変更します。例:
$ docker run -d \
--name wordpress \
--publish 80:80 \
--restart=unless-stopped \
-e WORDPRESS_DB_HOST=proxysql2:6033 \
-e WORDPRESS_DB_USER=wordpress \
-e WORDPRESS_DB_HOST=passw0rd \
wordpress
この時点で、私たちのアーキテクチャは次のようになっています。
ProxySQLコンテナを永続的にする場合は、/ var / lib / proxysql /をDockerボリュームにマップするか、マウントをバインドします(例:
)。$ docker run -d \
--name proxysql2 \
--hostname proxysql2 \
--publish 6033:6033 \
--publish 6032:6032 \
--publish 6080:6080 \
--restart=unless-stopped \
-v /root/proxysql/proxysql.cnf:/etc/proxysql.cnf \
-v proxysql-volume:/var/lib/proxysql \
severalnines/proxysql:2.0
上記のような永続ストレージで実行すると、2回目の再起動時に/root/proxysql/proxysql.cnfが廃止されることに注意してください。これは、ProxySQLマルチレイヤー構成が原因で、/ var / lib / proxysql / proxysql.dbが存在する場合、ProxySQLは構成ファイルからのオプションの読み込みをスキップし、代わりにSQLiteデータベースにあるものを読み込みます(--initialでproxysqlサービスを開始しない限り)国旗)。そうは言っても、次のProxySQL構成管理は、構成ファイルを使用する代わりに、ポート6032のProxySQL管理コンソールを介して実行する必要があります。
監視
ProxySQLプロセスログはデフォルトでsyslogに記録され、標準のdockerコマンドを使用して表示できます:
$ docker ps
$ docker logs proxysql2
現在のホストグループを確認するには、runtime_mysql_serversテーブルをクエリします。
$ docker exec -it proxysql2 mysql -uadmin -padmin -h127.0.0.1 -P6032 --prompt='Admin> '
Admin> select hostgroup_id,hostname,status from runtime_mysql_servers;
+--------------+--------------+--------+
| hostgroup_id | hostname | status |
+--------------+--------------+--------+
| 10 | 192.168.0.21 | ONLINE |
| 30 | 192.168.0.21 | ONLINE |
| 30 | 192.168.0.22 | ONLINE |
| 30 | 192.168.0.23 | ONLINE |
| 20 | 192.168.0.22 | ONLINE |
| 20 | 192.168.0.23 | ONLINE |
+--------------+--------------+--------+
選択したライターがダウンした場合、offline_hostgroup(HID 9999)に転送されます:
Admin> select hostgroup_id,hostname,status from runtime_mysql_servers;
+--------------+--------------+--------+
| hostgroup_id | hostname | status |
+--------------+--------------+--------+
| 10 | 192.168.0.22 | ONLINE |
| 9999 | 192.168.0.21 | ONLINE |
| 30 | 192.168.0.22 | ONLINE |
| 30 | 192.168.0.23 | ONLINE |
| 20 | 192.168.0.23 | ONLINE |
+--------------+--------------+--------+
上記のトポロジの変更は、次の図に示されています。
また、admin-web_enabled =trueを使用してWeb統計UIを有効にしました。WebUIにアクセスするには、ポート6080のDockerホストにアクセスします(例: http://192.168.0.200:8060 )。 ユーザー名/パスワードのポップアップが表示されます。 admin-stats_credentialsで定義されているクレデンシャルを入力すると、次のページが表示されます。
MySQL接続プールテーブルを監視することで、すべてのホストグループの接続分散の概要を取得できます。
Admin> select hostgroup, srv_host, status, ConnUsed, MaxConnUsed, Queries from stats.stats_mysql_connection_pool order by srv_host;
+-----------+--------------+--------+----------+-------------+---------+
| hostgroup | srv_host | status | ConnUsed | MaxConnUsed | Queries |
+-----------+--------------+--------+----------+-------------+---------+
| 20 | 192.168.0.23 | ONLINE | 5 | 24 | 11458 |
| 30 | 192.168.0.23 | ONLINE | 0 | 0 | 0 |
| 20 | 192.168.0.22 | ONLINE | 2 | 24 | 11485 |
| 30 | 192.168.0.22 | ONLINE | 0 | 0 | 0 |
| 10 | 192.168.0.21 | ONLINE | 32 | 32 | 9746 |
| 30 | 192.168.0.21 | ONLINE | 0 | 0 | 0 |
+-----------+--------------+--------+----------+-------------+---------+
上記の出力は、クエリルールでこのホストグループが宛先ホストグループとして構成されていないため、ホストグループ30は何も処理しないことを示しています。
Galeraノードに関連する統計は、mysql_server_galera_logテーブルで表示できます。
Admin> select * from mysql_server_galera_log order by time_start_us desc limit 3\G
*************************** 1. row ***************************
hostname: 192.168.0.23
port: 3306
time_start_us: 1552992553332489
success_time_us: 2045
primary_partition: YES
read_only: NO
wsrep_local_recv_queue: 0
wsrep_local_state: 4
wsrep_desync: NO
wsrep_reject_queries: NO
wsrep_sst_donor_rejects_queries: NO
error: NULL
*************************** 2. row ***************************
hostname: 192.168.0.22
port: 3306
time_start_us: 1552992553329653
success_time_us: 2799
primary_partition: YES
read_only: NO
wsrep_local_recv_queue: 0
wsrep_local_state: 4
wsrep_desync: NO
wsrep_reject_queries: NO
wsrep_sst_donor_rejects_queries: NO
error: NULL
*************************** 3. row ***************************
hostname: 192.168.0.21
port: 3306
time_start_us: 1552992553329013
success_time_us: 2715
primary_partition: YES
read_only: NO
wsrep_local_recv_queue: 0
wsrep_local_state: 4
wsrep_desync: NO
wsrep_reject_queries: NO
wsrep_sst_donor_rejects_queries: NO
error: NULL
結果セットは、特定のタイムスタンプのすべてのGaleraノードに関連するMySQL変数/ステータス状態を返します。この構成では、Galeraヘルスチェックを2秒ごとに実行するように構成しました(monitor_galera_healthcheck_interval =2000)。したがって、トポロジの変更がクラスタに発生した場合、最大フェイルオーバー時間は約2秒になります。
参照
- ProxySQLネイティブガレラサポート
- HAおよびクラスタリングソリューション:Galeraおよびグループレプリケーション用のインテリジェントルーターとしてのProxySQL
- SevereninesによるProxySQLDockerイメージ
- PrometheusとClusterControlを使用してProxySQLを監視する方法