Galera Replicationはじめます
MySQL

Galera Replicationはじめます

このエントリーをはてなブックマークに追加

はじめまして。
GMOメディア サービス開発部 DBAの田中と申します。 

当社ではMySQLを利用しているサービスが数あり、
その冗長化構成はSemi-Sync Replicationのものがほとんどなのですが、

Semi-Syncは個人的にどうも好きになれないし
mysqlfailoverはpythonで書かれているので嫌

マスター切り替えの仕組みやサービスに戻す手順を簡素化したい、
書き込みもスケールアップさせてサーバー統合したい、
ついでにバックアップ用サーバーを統合してサーバーを減らしたい

そんなことを考えてGalera Replicationの導入を目論んでいます。
実装としてリリースされているPercona XtraDB ClusterMariaDB 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_addressを戻して。

$ 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)
クラスター起動できた!

やー。。
長かった。。 

マニュアル読めってただの恥さらしですね。


名無しのエンジニア
第6回WebUX研究会にいってきました!
初心者でも分かるRailsで始めるHeroku入門 その1