EC2でMySQL(運用編 VP+Spiderで無停止負荷分散)などを紹介してきましたが、再び、Spiderの話題になります。
WEBアプリを世界展開する際に、要件の1つとして、世界各国のユーザは全てのデータを参照できる必要がありますが、データの登録は各国、地域の担当者が各自のデータを登録したい、というケースが多々あると思います。
例として、商品の販売サイトで、EUと日本にそれぞれ管理者がいるとします。
その場合のユースケースとしては、下記となります。
- EUの管理者はEUの商品を登録する
- 日本の管理者は日本の商品を登録する
- ユーザーは全ての商品を閲覧できる
この時、商品を登録するDBがどのリージョンにあるかによって、ユーザや管理者の間でレスポンススピードに差が出ます。
DBを日本に置くとEUのユーザや管理者には遅いシステムとなってしまい、EUに置くとその逆になります。
そのため、各リージョンに全てのリージョンで登録した商品データを用意し、ユーザのロケーションに関わらず、DBアクセスをユーザと同じリージョン内で済ませる必要があります。
管理者がアクセスするDBも管理者のいるリージョン内で済ませる必要があります。
この仕組みをSpiderとレプリケーションで実現してみます。
上図を見ると検討が付くかも知れませんが、方法としてはEUとJPそれぞれのリージョンに属する商品マスタに対して書き込み、EUではJPの、JPはEUのスレーブを持ち、それぞれをSpiderでシャーディングします。
DBの図で表すと、下記のようになります。
それでは実際に試してみます。
○データノード
CREATE TABLE item ( id int(11) NOT NULL AUTO_INCREMENT, name varchar(256) DEFAULT NULL, shop_id int(11) DEFAULT NULL, region_id int(11) NOT NULL DEFAULT '0', PRIMARY KEY (id, region_id) ) ENGINE=SPIDER DEFAULT CHARSET=utf8 ;
○Spiderノード
spider_ja
CREATE TABLE item ( id int(11) NOT NULL AUTO_INCREMENT, name varchar(256) DEFAULT NULL, shop_id int(11) DEFAULT NULL, region_id int(11) NOT NULL DEFAULT '0', PRIMARY KEY (id, region_id) ) ENGINE=SPIDER DEFAULT CHARSET=utf8 CONNECTION=' table "item", user "remote_user", password "remote_pass" ' PARTITION BY LIST (region_id) ( PARTITION ja_ja VALUES IN (1) COMMENT = 'host "111.111.0.1", port "3306"', PARTITION ja_eu VALUES IN (2) COMMENT = 'host "111.111.0.2", port "3306"' ) ;
spider_eu
CREATE TABLE item ( id int(11) NOT NULL AUTO_INCREMENT, name varchar(256) DEFAULT NULL, shop_id int(11) DEFAULT NULL, region_id int(11) NOT NULL DEFAULT '0', PRIMARY KEY (id, region_id) ) ENGINE=SPIDER DEFAULT CHARSET=utf8 CONNECTION=' table "item", user "remote_user", password "remote_pass" ' PARTITION BY LIST (region_id) ( PARTITION eu_ja VALUES IN (1) COMMENT = 'host "222.222.0.1", port "3306"', PARTITION eu_eu VALUES IN (2) COMMENT = 'host "222.222.0.2", port "3306"' ) ;
○レプリケーション
ja-eu
$ mysql -u root mysql> CHANGE MASTER TO MASTER_HOST='222.222.0.2', MASTER_USER='remote_user', MASTER_PASSWORD='remote_user', MASTER_PORT=3306;
eu-ja
$ mysql -u root mysql> CHANGE MASTER TO MASTER_HOST='111.111.0.1', MASTER_USER='remote_user', MASTER_PASSWORD='remote_user', MASTER_PORT=3306;
※各ノード間のアクセス権限やサーバーIDの登録、セキュリティグループの設定などは以前の記事に書いたので割愛します。
注意点としては、region_id(1:ja, 2:eu)のLISTパーティションにするため、プライマリキーをidとregion_idの複合キーにするところになります。
INSERT時には、登録したリージョンのregion_idをセットします。
※登録したリージョンではないregion_idをセットするとパーティションに含まれず、シャーディング対象にならないので、注意が必要です。
spider-ja
mysql> INSERT INTO item (name, shop_id, region_id) VALUES('おいしい水', 1, 1), ('おしゃれなバッグ', 2, 1); Query OK, 2 rows affected (0.02 sec) Records: 2 Duplicates: 0 Warnings: 0
spider-eu
mysql> insert into item(name,shop_id,region_id) values('Cool Watch', 3, 2),('Cute Ring', 4, 2); Query OK, 2 rows affected (0.03 sec) Records: 2 Duplicates: 0 Warnings: 0
以上により、それぞれのspiderノードで全てのitemをselectすることができます。
mysql> select * from item; +----+--------------------------+---------+-----------+ | id | name | shop_id | region_id | +----+--------------------------+---------+-----------+ | 1 | おいしい水 | 1 | 1 | | 2 | おしゃれなバッグ | 2 | 1 | | 1 | Cool Watch | 3 | 2 | | 2 | Cute Ring | 4 | 2 | +----+--------------------------+---------+-----------+ 4 rows in set (0.01 sec)
このように、リージョンが分かれている場合でも、アクセス速度を気にすること無くシャーディングができました。
こちらの記事はなかの人(memorycraft)監修のもと掲載しています。
元記事は、こちら