この記事は
MySQL Fabric&Routerつらくない Advent Calendar 2015 の25日目の記事です。
まずはどうやって遅延を計測しようか考えているメモをだだだと書きなぐる。後半にまとめっぽいものを。
計測環境。サーバーもクライアントもc4.xlarge。サーバーはyumリポジトリーで5.7.10を突っ込んで起動しただけ。
# rpm -i http://dev.mysql.com/get/mysql57-community-release-el6-7.noarch.rpm
# yum install -y mysql-community-server
# service mysqld start
# grep password /var/log/mysqld.log
# mysql -p
mysql> UNINSTALL PLUGIN validate_password;
mysql> CREATE USER yoku0825;
クライアントは接続してSELECT NOW()して切断するだけのもの。
$ cat -n test.cc
1 #include <unistd.h>
2 #include "mysql.h"
3
4 int main()
5 {
6 MYSQL mysql;
7 int m;
8
9 mysql_init(&mysql);
10
11 for (m= 0; m <= 10000; m++)
12 {
13 mysql_real_connect(&mysql, "172.31.15.74", "yoku0825", "", NULL,
14 3306, NULL, 0);
15 mysql_query(&mysql, "SELECT NOW()");
16 MYSQL_RES *res= mysql_store_result(&mysql);
17 mysql_close(&mysql);
18 }
19 }
$ gcc -I/usr/include/mysql -L/usr/lib64/mysql -lmysqlclient -g3 -O0 test.cc
$ time ./a.out
real 0m6.865s
user 0m0.248s
sys 0m0.552s
直接接続だと大体700usくらい。
c4.xlargeは4コアあるので4つ起動してみると
$ time (./a.out & ./a.out & ./a.out & ./a.out ; wait)
real 0m22.573s
user 0m0.508s
sys 1m10.168s
これくらい。ダメだ。ほとんどsysにもっていかれてる。まともに並列処理を書けるC力がほしい。
Routerはソースからコンパイル。サーバーホストだけを指定して単にプロキシーするだけの状態にする。
$ wget http://dev.mysql.com/get/Downloads/MySQL-Router/mysql-router-2.0.2.tar.gz
$ tar xf mysql-router-2.0.2.tar.gz
$ cd mysql-router-2.0.2
$ cmake .
$ make
$ sudo make install
$ sudo cp -ip /usr/local/share/doc/mysqlrouter/sample_mysqlrouter.ini /usr/local/etc/mysqlrouter/mysqlrouter.ini
$ sudo vim /usr/local/etc/mysqlrouter/mysqlrouter.ini
..
[routing:basic_failover]
# To be more transparent, use MySQL Server port 3306
bind_port = 7001
mode = read-write
destinations = 172.31.15.74
..
mysql_real_connectの向き先を127.0.0.1:7001に変えて、中央値は大体これくらい。
$ time ./a.out
real 0m8.816s
user 0m0.192s
sys 0m0.916s
$ time (./a.out & ./a.out & ./a.out & ./a.out ; wait)
real 0m9.761s
user 0m1.432s
sys 0m4.192s
コンテキストスイッチが減ってRouter経由の方が快適という結果に。top見てても遥かに良い感じ(mysqlrouterが100%張り付くので、a.outは20%くらいずつになる。これが結果として綺麗にキャップになっていい感じになるという。。)
もっとちゃんとしたクライアントだと、シングルスレッドのmysqlrouterが問題になってくると思う。取り敢えず、10秒で10000コネクション * 4プロセスだから4000connection/sならさばけてる(mysqlrouterの%usrが張り付くけど)
これを超えてくる場合、mysqlrouterのプロセスを複数起動して分散させることになるし、MySQL Routerはどうやら動的に設定を変えることはできないので、gracefulっぽくするためには
tcpdump + pt-query-digestでレイテンシーを見てみると、直接接続の場合はmysql_real_connectの中央値が467usにクエリーの中央値が152us。
# Query 1: 1.40k QPS, 0.70x concurrency, ID 0x5D51E5F01B88B79E at byte 42297981
# This item is included in the report because it matches --limit.
# Scores: V/M = 0.00
# Time range: 2015-12-24 10:33:50.782145 to 10:33:57.922968
# Attribute pct total min max avg 95% stddev median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count 33 10000
# Exec time 75 5s 431us 1ms 498us 568us 39us 467us
# Rows affecte 0 0 0 0 0 0 0 0
# Query size 43 292.97k 30 30 30 30 0 30
# Warning coun 0 0 0 0 0 0 0 0
# String:
# Databases
# Hosts 172.31.5.70
# Users yoku0825
# Query_time distribution
# 1us
# 10us
# 100us ################################################################
# 1ms #
# 10ms
# 100ms
# 1s
# 10s+
administrator command: Connect\G
# Query 2: 1.40k QPS, 0.22x concurrency, ID 0xF450CBDB69FA3A64 at byte 42299217
# This item is included in the report because it matches --limit.
# Scores: V/M = 0.00
# Time range: 2015-12-24 10:33:50.782371 to 10:33:57.923132
# Attribute pct total min max avg 95% stddev median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count 33 10000
# Exec time 24 2s 142us 419us 159us 204us 16us 152us
# Rows affecte 0 0 0 0 0 0 0 0
# Query size 17 117.19k 12 12 12 12 0 12
# Warning coun 0 0 0 0 0 0 0 0
# String:
# Databases
# Hosts 172.31.5.70
# Users yoku0825
# Query_time distribution
# 1us
# 10us
# 100us ################################################################
# 1ms
# 10ms
# 100ms
# 1s
# 10s+
# EXPLAIN /*!50100 PARTITIONS*/
SELECT NOW()\G
Router経由だと固定でレイテンシーがあがるだけだと思ってたけど、Connectの方がぁゃιぃ。フツーのクエリーを計測するよりも(ルーティング判定のぶん)コストが高そう。もうちょっと別のクエリーも投げるパターンにして計測しないとダメだ。
単純クエリーで10usくらいの差なら、まともなクエリーになるに従って十分問題ないと見ていいはず。あ、でも、往復のパケット量が増えればそれぞれのパケットにレイテンシーが載るから結果セットが転送されきるまでのレイテンシーは無視できないのかも知れない。これも計測パターン増やさないと。
# Query 1: 1.07k QPS, 0.62x concurrency, ID 0x5D51E5F01B88B79E at byte 5655092
# This item is included in the report because it matches --limit.
# Scores: V/M = 0.00
# Time range: 2015-12-24 10:35:26.307560 to 10:35:35.641810
# Attribute pct total min max avg 95% stddev median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count 33 10000
# Exec time 76 6s 488us 1ms 581us 690us 65us 541us
# Rows affecte 0 0 0 0 0 0 0 0
# Query size 43 292.97k 30 30 30 30 0 30
# Warning coun 0 0 0 0 0 0 0 0
# String:
# Databases
# Hosts 172.31.5.70
# Users yoku0825
# Query_time distribution
# 1us
# 10us
# 100us ################################################################
# 1ms #
# 10ms
# 100ms
# 1s
# 10s+
administrator command: Connect\G
# Query 2: 1.07k QPS, 0.19x concurrency, ID 0xF450CBDB69FA3A64 at byte 45635077
# This item is included in the report because it matches --limit.
# Scores: V/M = 0.00
# Time range: 2015-12-24 10:35:26.307968 to 10:35:35.642044
# Attribute pct total min max avg 95% stddev median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count 33 10000
# Exec time 23 2s 145us 577us 174us 214us 28us 159us
# Rows affecte 0 0 0 0 0 0 0 0
# Query size 17 117.19k 12 12 12 12 0 12
# Warning coun 0 0 0 0 0 0 0 0
# String:
# Databases
# Hosts 172.31.5.70
# Users yoku0825
# Query_time distribution
# 1us
# 10us
# 100us ################################################################
# 1ms
# 10ms
# 100ms
# 1s
# 10s+
# EXPLAIN /*!50100 PARTITIONS*/
SELECT NOW()\G
MySQL Fabricが載ってくると当然結果は変わるだろうから、次はFabric Cache Pluginバージョンも試す(台数がかさむなぁ。。)
ダラダラ書いたけど、次に測らないといけないところはわかった気がする。
さて、本題(?)
MySQL Routerは本当につらくなかったのか?
残念ながら つらくなかったです。
# 情報量(主にドキュメント)
* 初期のMySQL Fabricはひどかった。
* それよりは、今のMySQL Routerはマシ。
* ただし、今のMySQL Fabricの方がMySQL Routerより情報ある(と思う)
* つまり、結局は今後に期待。
* ただ、MySQL FabricよりはMySQL Routerの方が流行ると思うので、日本語の情報も充実していくんじゃないかなぁ。
# 安定性
* MySQL Fabricも良くなってるんじゃないか疑惑
*
去年試してた時 は結構さっくり刺さってハングしてたけど、今年は1回も突き刺さってない
* MySQL Routerは取り敢えず安定。
Fabric Cache Plugin使ってる時の動作が若干不安…?
* 再現しないので、要追試。
# 使いやすさ、使いたさ
## MySQL Fabric
* グラフィカルなCLIでレプリケーションクラスターの管理。したい。
* GTID依存なので、まずGTIDをONにして回るのが大変。
* バックアップからリストアしたやつをレプリケーションクラスターに追加とかもGTID依存なので、5.6だと苦労しそう(5.7ならきっといける)
* GTID依存だからこそ色々簡単なんだよなー、と思うとGTIDはやっぱりいいものだったのだな。
* MariaDBさんがいるとダメ(GTIDの実装が全然違って互換性がない)
* いろんな実装がコネクター依存すぎてブラックボックスが超怖い。Connector/Jでは上手くいくけど他はダメとかフツーにありそう。
## MySQL Router
* 次世代MySQL Proxyとして使い始められる
* スレーブの分散、Routerに置き換えようかと真面目に検討中。
* Lua書かなくていい。ただし、MySQL RouterのプラグインはC++な上にドキュメントがまだないぽい。
* Fabric Cache PluginはMySQL Fabricのブラックボックスを解消するものなので、とてもイケていると思う。
* ただ、アレだけで1章書いてもいいんじゃないかってくらいもっと説明して欲しいところがいっぱいある。。
* MySQL Fabricと連携させないなら、
4.0 5.5とかでもイケるんじゃないかな(old_passwordの壁があるか…?)
# デバッグとソースコードリーディング
* MySQL FabricはPythonで、俺のPython力の欠如によりつらかった
* ゆるぼ: Pythonista
* MySQL RouterはC++でgdbで突き刺すスタイルなのでデバッグが楽
* とはいえこれはMySQLオタク向けの項目なので、ほとんどの人には無縁
というわけで!
つらくないよ!
つらくないから、僕と結託して
地雷 MySQL Router友達になってよ!
お待ちしております :)