Galera Replicationはじめます

はじめまして。
GMOメディア サービス開発部 DBAの田中と申します。
当社ではMySQLを利用しているサービスが数あり、
その冗長化構成はSemi-Sync Replicationのものがほとんどなのですが、
Semi-Syncは個人的にどうも好きになれないし
mysqlfailoverはpythonで書かれているので嫌
マスター切り替えの仕組みやサービスに戻す手順を簡素化したい、
書き込みもスケールアップさせてサーバー統合したい、
ついでにバックアップ用サーバーを統合してサーバーを減らしたい
そんなことを考えてGalera Replicationの導入を目論んでいます。
実装としてリリースされているPercona XtraDB ClusterかMariaDB Galera Clusterを使うことになるので、
目下性能面と安定面で本番投入に耐えうるかどうかのテストなどしています。
なお、Galera Replicationを選んだのは個人的な野望で、
社内的には"MySQL5.6 + mysqlfailoverで全て解決するよ!"的な流れで肩身は狭いですが。
GTIDは バグが多くて嫌い 新規機能で安定面にまだ問題がある気がするので、
5.6がGAになってももう少し待ちたいかなと思っています。。
さてさて、そんな私がPercona XtraDB Clusterを導入した時にハマったメモです。
日本語情報少ない気がするので、ちょこちょこ残していければと思います。
インストールするところまでは、バイナリの.tar.gz をダウンロードしてきて普段のMySQLと同じく設置します。
さて、いつもの./scripts/mysql_install_db
。
$ ./scripts/mysql_install_db --datadir=./data WARNING: The host 'test-mysqlHA03' could not be looked up with resolveip. This probably means that your libc libraries are not 100 % compatible with this binary MySQL version. The MySQL daemon, mysqld, should work normally with the exception that host name resolving will not work. This means that you should use IP addresses instead of hostnames when specifying MySQL privileges !
Installing MySQL system tables... 130125 12:31:35 [ERROR] WSREP: Only binlog_format = 'ROW' is currently supported. Configured value: 'mixed'. Please adjust your configuration. 130125 12:31:35 [ERROR] Aborting
あれ、怒られました。
そういえばbinlog_format=ROW
は必須とマニュアルにも書いてあるのでやり直し(先に/etc/my.cnf
に書いてもOK)
$ ./scripts/mysql_install_db --datadir=./data --binlog-format=row WARNING: The host 'test-mysqlHA03' could not be looked up with resolveip. This probably means that your libc libraries are not 100 % compatible with this binary MySQL version. The MySQL daemon, mysqld, should work normally with the exception that host name resolving will not work. This means that you should use IP addresses instead of hostnames when specifying MySQL privileges ! Installing MySQL system tables... OK Filling help tables... OK
できました。
さてmy.cnfを作りますが、ドキュメントを読みながら必須オプションを追加。
Exampleを参考にして、いざ起動。
$ bin/mysqld_safe --defaults-file=./my.cnf & [1] 9986 130125 12:53:35 mysqld_safe Logging to '/xtra/data/error.log'. 130125 12:53:35 mysqld_safe Starting mysqld daemon with databases from /xtra/data 130125 12:53:35 mysqld_safe WSREP: Running position recovery with --log_error=/tmp/tmp.rVMWWN48M2 nohup: ignoring input and appending output to `nohup.out' 130125 12:53:41 mysqld_safe WSREP: Recovered position 00000000-0000-0000-0000-000000000000:-1 130125 12:54:16 mysqld_safe mysqld from pid file /xtra/data/test-mysqlHA03.pid ended [1]+ Done bin/mysqld_safe --defaults-file=./my.cnf
$ cat data/error.log 130125 12:53:35 mysqld_safe Starting mysqld daemon with databases from /xtra/data 130125 12:53:35 mysqld_safe WSREP: Running position recovery with --log_error=/tmp/tmp.rVMWWN48M2 130125 12:53:41 mysqld_safe WSREP: Recovered position 00000000-0000-0000-0000-000000000000:-1 130125 12:53:41 [Note] WSREP: wsrep_start_position var submitted: '00000000-0000-0000-0000-000000000000:-1' 130125 12:53:41 [Note] WSREP: Read nil XID from storage engines, skipping position init 130125 12:53:41 [Note] WSREP: wsrep_load(): loading provider library '/xtra/lib/libgalera_smm.so' 130125 12:53:42 [Note] WSREP: wsrep_load(): Galera 2.2(r137) by Codership Oy <info@codership.com> loaded succesfully. 130125 12:53:42 [Warning] WSREP: Could not open saved state file for reading: /xtra/data//grastate.dat 130125 12:53:42 [Note] WSREP: Found saved state: 00000000-0000-0000-0000-000000000000:-1 130125 12:53:42 [Note] WSREP: Preallocating 134219048/134219048 bytes in '/xtra/data//galera.cache'... 130125 12:53:42 [Note] WSREP: Passing config to GCS: base_host = 192.168.199.133; base_port = 4567; cert.log_conflicts = no; gcache.dir = /xtra/data/; gcache.keep_pages_size = 0; gcache.mem_size = 0; gcache.name = /xtra/data//galera.cache; gcache.page_size = 128M; gcache.size = 128M; gcs.fc_debug = 0; gcs.fc_factor = 1; gcs.fc_limit = 16; gcs.fc_master_slave = NO; gcs.max_packet_size = 64500; gcs.max_throttle = 0.25; gcs.recv_q_hard_limit = 9223372036854775807; gcs.recv_q_soft_limit = 0.25; gcs.sync_donor = NO; replicator.causal_read_timeout = PT30S; replicator.commit_order = 3 130125 12:53:42 [Note] WSREP: Assign initial position for certification: -1, protocol version: -1 130125 12:53:42 [Note] WSREP: wsrep_sst_grab() 130125 12:53:42 [Note] WSREP: Start replication 130125 12:53:42 [Note] WSREP: Setting initial position to 00000000-0000-0000-0000-000000000000:-1 130125 12:53:42 [Note] WSREP: protonet asio version 0 130125 12:53:42 [Note] WSREP: backend: asio 130125 12:53:42 [Note] WSREP: GMCast version 0 130125 12:53:42 [Note] WSREP: (cf3fe640-66a2-11e2-0800-61ffd6130c94, 'tcp://0.0.0.0:4567') listening at tcp://0.0.0.0:4567 130125 12:53:42 [Note] WSREP: (cf3fe640-66a2-11e2-0800-61ffd6130c94, 'tcp://0.0.0.0:4567') multicast: , ttl: 1 130125 12:53:42 [Note] WSREP: EVS version 0 130125 12:53:42 [Note] WSREP: PC version 0 130125 12:53:42 [Note] WSREP: gcomm: connecting to group 'xtra', peer '192.168.199.133:' 130125 12:53:42 [Warning] WSREP: (cf3fe640-66a2-11e2-0800-61ffd6130c94, 'tcp://0.0.0.0:4567') address 'tcp://192.168.199.133:4567' points to own listening address, blacklisting 130125 12:53:45 [Warning] WSREP: no nodes coming from prim view, prim not possible 130125 12:53:45 [Note] WSREP: view(view_id(NON_PRIM,cf3fe640-66a2-11e2-0800-61ffd6130c94,1) memb { cf3fe640-66a2-11e2-0800-61ffd6130c94, } joined { } left { } partitioned { }) 130125 12:53:45 [Warning] WSREP: last inactive check more than PT1.5S ago, skipping check 130125 12:54:15 [Note] WSREP: view((empty)) 130125 12:54:15 [ERROR] WSREP: failed to open gcomm backend connection: 110: failed to reach primary view: 110 (Connection timed out) at gcomm/src/pc.cpp:connect():157 130125 12:54:15 [ERROR] WSREP: gcs/src/gcs_core.c:gcs_core_open():195: Failed to open backend connection: -110 (Connection timed out) 130125 12:54:15 [ERROR] WSREP: gcs/src/gcs.c:gcs_open():1290: Failed to open channel 'xtra' at 'gcomm://192.168.199.133': -110 (Connection timed out) 130125 12:54:15 [ERROR] WSREP: gcs connect failed: Connection timed out 130125 12:54:15 [ERROR] WSREP: wsrep::connect() failed: 6 130125 12:54:15 [ERROR] Aborting 130125 12:54:15 [Note] WSREP: Service disconnected. 130125 12:54:16 [Note] WSREP: Some threads may fail to exit. 130125 12:54:16 [Note] /xtra/bin/mysqld: Shutdown complete
130125 12:54:16 mysqld_safe mysqld from pid file /xtra/data/test-
後ろから順番に読んでいくと、wsrep::connect()
に失敗。原因はConnection timed out。
Warningで192.168.199.133:4567は自分のアドレスだからブラックリスト行きだぜーとか稼動機が繋ぎに来ないぜーとか言っている。
(Galera Replicationのノード参加時は、 既に稼動しているノードから新規ノードにアクセスしてくる仕組みになっている)
ここかなぁ…? ExampleからIPアドレス変えただけ。192.168.199.133は自分のアドレス。
wsrep_cluster_address = gcomm://192.168.199.133
クラスターの最初の一台だから、指定しない方が良いのかな? と思ってコメントアウト。れつごー。
$ bin/mysqld_safe --defaults-file=./my.cnf & [1] 15155 130125 13:31:41 mysqld_safe Logging to '/xtra/data/error.log'. 130125 13:31:41 mysqld_safe Starting mysqld daemon with databases from /xtra/data 130125 13:31:41 mysqld_safe WSREP: Running position recovery with --log_error=/tmp/tmp.z1crIjQdeB nohup: ignoring input and appending output to `nohup.out' 130125 13:31:47 mysqld_safe WSREP: Recovered position 00000000-0000-0000-0000-000000000000:-1
$ bin/mysql --defaults-file=./my.cnf Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 11 Server version: 5.5.28-23.7-log .. mysql> STATUS ERROR 1047 (08S01): Unknown command
STATUSコマンドに対してUnknown commandが返ってくるのは、クラスター内で1台しか起動していない状態ではあらゆるコマンドを拒否する仕様のため。
じゃあ、2台目上げますかー。
1台目と2台目でwsrep_node_name
だけ変えて、1台目でコメントアウトしたwsrep_cluster_addres
sを戻して。
$ bin/mysqld_safe --defaults-file=./my.cnf & [1] 9211 130125 14:01:44 mysqld_safe Logging to '/xtra/data/error.log'. 130125 14:01:44 mysqld_safe Starting mysqld daemon with databases from /xtra/data 130125 14:01:44 mysqld_safe WSREP: Running position recovery with --log_error=/tmp/tmp.HiDQyv3Dlf nohup: ignoring input and appending output to `nohup.out' 130125 14:01:52 mysqld_safe WSREP: Recovered position 00000000-0000-0000-0000-000000000000:-1 130125 14:02:28 mysqld_safe mysqld from pid file /xtra/data/test-mysqlHA02.pid ended
あれ。
$ cat data/error.log 130125 14:01:44 mysqld_safe Starting mysqld daemon with databases from /xtra/data 130125 14:01:44 mysqld_safe WSREP: Running position recovery with --log_error=/tmp/tmp.HiDQyv3Dlf 130125 14:01:52 mysqld_safe WSREP: Recovered position 00000000-0000-0000-0000-000000000000:-1 130125 14:01:53 [Note] WSREP: wsrep_start_position var submitted: '00000000-0000-0000-0000-000000000000:-1' 130125 14:01:53 [Note] WSREP: Read nil XID from storage engines, skipping position init 130125 14:01:53 [Note] WSREP: wsrep_load(): loading provider library '/xtra/lib/libgalera_smm.so' 130125 14:01:53 [Note] WSREP: wsrep_load(): Galera 2.2(r137) by Codership Oy <info@codership.com> loaded succesfully. 130125 14:01:53 [Warning] WSREP: Could not open saved state file for reading: /xtra/data//grastate.dat 130125 14:01:53 [Note] WSREP: Found saved state: 00000000-0000-0000-0000-000000000000:-1 130125 14:01:53 [Note] WSREP: Preallocating 134219048/134219048 bytes in '/xtra/data//galera.cache'... 130125 14:01:53 [Note] WSREP: Passing config to GCS: base_host = 192.168.199.132; base_port = 4567; cert.log_conflicts = no; gcache.dir = /xtra/data/; gcache.keep_pages_size = 0; gcache.mem_size = 0; gcache.name = /xtra/data//galera.cache; gcache.page_size = 128M; gcache.size = 128M; gcs.fc_debug = 0; gcs.fc_factor = 1; gcs.fc_limit = 16; gcs.fc_master_slave = NO; gcs.max_packet_size = 64500; gcs.max_throttle = 0.25; gcs.recv_q_hard_limit = 9223372036854775807; gcs.recv_q_soft_limit = 0.25; gcs.sync_donor = NO; replicator.causal_read_timeout = PT30S; replicator.commit_order = 3 130125 14:01:53 [Note] WSREP: Assign initial position for certification: -1, protocol version: -1 130125 14:01:53 [Note] WSREP: wsrep_sst_grab() 130125 14:01:53 [Note] WSREP: Start replication 130125 14:01:53 [Note] WSREP: Setting initial position to 00000000-0000-0000-0000-000000000000:-1 130125 14:01:53 [Note] WSREP: protonet asio version 0 130125 14:01:53 [Note] WSREP: backend: asio 130125 14:01:53 [Note] WSREP: GMCast version 0 130125 14:01:53 [Note] WSREP: (561e9418-66ac-11e2-0800-68daf3e907aa, 'tcp://0.0.0.0:4567') listening at tcp://0.0.0.0:4567 130125 14:01:53 [Note] WSREP: (561e9418-66ac-11e2-0800-68daf3e907aa, 'tcp://0.0.0.0:4567') multicast: , ttl: 1 130125 14:01:53 [Note] WSREP: EVS version 0 130125 14:01:53 [Note] WSREP: PC version 0 130125 14:01:53 [Note] WSREP: gcomm: connecting to group 'xtra', peer '192.168.199.133:' 130125 14:01:56 [Warning] WSREP: no nodes coming from prim view, prim not possible 130125 14:01:56 [Note] WSREP: view(view_id(NON_PRIM,561e9418-66ac-11e2-0800-68daf3e907aa,1) memb { 561e9418-66ac-11e2-0800-68daf3e907aa, } joined { } left { } partitioned { }) 130125 14:01:57 [Warning] WSREP: last inactive check more than PT1.5S ago, skipping check 130125 14:02:27 [Note] WSREP: view((empty)) 130125 14:02:27 [ERROR] WSREP: failed to open gcomm backend connection: 110: failed to reach primary view: 110 (Connection timed out) at gcomm/src/pc.cpp:connect():157 130125 14:02:27 [ERROR] WSREP: gcs/src/gcs_core.c:gcs_core_open():195: Failed to open backend connection: -110 (Connection timed out) 130125 14:02:27 [ERROR] WSREP: gcs/src/gcs.c:gcs_open():1290: Failed to open channel 'xtra' at 'gcomm://192.168.199.133': -110 (Connection timed out) 130125 14:02:27 [ERROR] WSREP: gcs connect failed: Connection timed out 130125 14:02:27 [ERROR] WSREP: wsrep::connect() failed: 6 130125 14:02:27 [ERROR] Aborting
130125 14:02:27 [Note] WSREP: Service disconnected. 130125 14:02:28 [Note] WSREP: Some threads may fail to exit. 130125 14:02:28 [Note] /xtra/bin/mysqld: Shutdown complete
130125 14:02:28 mysqld_safe mysqld from pid file /xtra/data/test-mysqlHA02.pid ended
1台目にwsrep_cluster_address
を指定してた時と同じログ。
tcpdumpを取ってみると、2台目のエフェメラルポートから1台目の4567番ポートにSYNを送ってはRSTを返されるということを繰り返している。
えー?
$ netstat -ant | grep LISTEN tcp 0 0 127.0.0.1:199 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
あれ…? 1台目で4567番ポートが浮いてない…?
さっきの、1台目にwsrep_cluster_address
を指定していてタイムアウトして落ちる状態では
$ netstat -ant | grep LISTEN
tcp 0 0 127.0.0.1:199 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:4567 0.0.0.0:* LISTEN
浮いてた。3306番ポート浮いてないけど。
えー、なにこれーと色々試してみたけれど、最終的には
cordership(Galera Replicationを開発しているところ)のWikiにあった
新しいクラスターを作る時には、wsrep_cluster_address=gcomm://
とだけ書けと。
1台目のmy.cnfを書き換えて
wsrep_cluster_address=gcom://
1台目を起動。
$ netstat -ant | grep LISTEN
tcp 0 0 127.0.0.1:199 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:4567 0.0.0.0:* LISTEN
3306番も4567番もLISTENしたよ!
2台目もさっき設定したそのまま、
wsrep_cluster_address=gcom://192.168.199.133
で起動。なんか上手く行ってるっぽい!
$ cat data/error.log
130125 14:22:04 mysqld_safe Starting mysqld daemon with databases from /xtra/data
130125 14:22:04 mysqld_safe WSREP: Running position recovery with --log_error=/tmp/tmp.EUAYI4WlaF
130125 14:22:10 mysqld_safe WSREP: Recovered position 00000000-0000-0000-0000-000000000000:-1
..
130125 14:22:10 [Note] WSREP: gcomm: connected
130125 14:22:10 [Note] WSREP: Changing maximum packet size to 64500, resulting msg size: 32636
130125 14:22:10 [Note] WSREP: Shifting CLOSED -> OPEN (TO: 0)
130125 14:22:10 [Note] WSREP: Opened channel 'xtra'
..
130125 14:22:10 [Note] WSREP: Shifting OPEN -> PRIMARY (TO: 0)
..
130125 14:22:13 [Note] WSREP: Shifting PRIMARY -> JOINER (TO: 0)
..
130125 14:22:19 [Note] WSREP: Shifting JOINER -> JOINED (TO: 0)
130125 14:22:19 [Note] WSREP: Member 0 (mysqlHA03) synced with group.
130125 14:22:19 [Note] WSREP: Shifting JOINED -> SYNCED (TO: 0)
130125 14:22:19 [Note] WSREP: Synchronized with group, ready for connections
130125 14:22:19 [Note] WSREP: wsrep_notify_cmd is not defined, skipping notification.
130125 14:22:19 [Note] /xtra/bin/mysqld: ready for connections.
Version: '5.5.28-23.7-log' socket: '/var/lib/mysql/mysql.sock' port: 3306 Percona XtraDB Cluster (GPL) 5.5.28-23.7, Revision 373, wsrep_23.7.r3821
よし、起動した!
mysql> show global status like 'wsrep%addr%'; +--------------------------+-------------------------------------------+ | Variable_name | Value | +--------------------------+-------------------------------------------+ | wsrep_incoming_addresses | 192.168.199.132:3306,192.168.199.133:3306 | +--------------------------+-------------------------------------------+ 1 row in set (0.00 sec)
やー。。
長かった。。
マニュアル読めってただの恥さらしですね。