2011年10月14日金曜日

EC2でMySQL(世界編2 Spiderとレプリケーションで高速負荷分散)

前回のつづきです。

前回はSpiderとレプリケーションで、リージョン間での高速なデータ分散を紹介しました。前回で少し触れましたが、この構成ではたとえばEU側のDBにJPのデータの書き込みには対応できません。

それを解決し、どちらのリージョンからもすべての商品を投入できるようにしてみたいと思います。
構成は以下のとおりです。



SpiderノードのDBで、書き込みと読み込みでそれぞれ別々のテーブルを用意し、別々のデータノードにそれぞれシャーディングを行います。

データノードの作成とレプリケーションの設定は前回と同じなので割愛します。

Spiderノード

spider_ja
CREATE TABLE item_r (
  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"'
)
;

CREATE TABLE item_w (
  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 eu_eu VALUES IN (2) COMMENT = 'host "222.222.0.2", port "3306"'
)
;

spider_eu
CREATE TABLE item_r (
  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"'
)
;

CREATE TABLE item_w (
  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 eu_eu VALUES IN (2) COMMENT = 'host "222.222.0.2", port "3306"'
)
;


item_wに対して書き込んでみます。
mysql> INSERT INTO item_w (name, shop_id, region_id) VALUES('おいしい水', 1, 1), ('おしゃれなバッグ', 2, 1), ('Cool Watch', 3, 2),('Cute Ring', 4, 2);
Query OK, 4 rows affected (1.95 sec)
Records: 4  Duplicates: 0  Warnings: 0


書き込みが成功しました。
item_wで参照すると、
mysql> select * from item_w;
+----+--------------------------+---------+-----------+
| id | name                     | shop_id | region_id |
+----+--------------------------+---------+-----------+
|  1 | おいしい水          |       1 |         1 |
|  2 | おしゃれなバッグ |       2 |         1 |
|  3 | Cool Watch               |       3 |         2 |
|  4 | Cute Ring                |       4 |         2 |
+----+--------------------------+---------+-----------+
4 rows in set (1.96 sec)
正しく投入されていることがわかりますが、レスポンスはやはり悪いです。

そこでitem_rで参照してみます。
mysql> select * from item_r;
+----+--------------------------+---------+-----------+
| id | name                     | shop_id | region_id |
+----+--------------------------+---------+-----------+
|  1 | おいしい水          |       1 |         1 |
|  2 | おしゃれなバッグ |       2 |         1 |
|  3 | Cool Watch               |       3 |         2 |
|  4 | Cute Ring                |       4 |         2 |
+----+--------------------------+---------+-----------+
4 rows in set (0.01 sec)
高速で読み込みできています。

これで、どちらのリージョンからも全リージョン用のデータの書き込みができ、なおかつ読み込みスピードを維持することが出来ました。

書き込み時は他方のリージョンにSpiderでアクセスするので、少し時間がかかります。
前回のように基本はJPのデータはJPリージョンから投入するようにルール化すれば書き込みスピードが損なわれることはありません。
すべてmicroインスタンスでの確認ということもあり、もしかしたらSpiderのサーバーやテーブルパラメータをいじることで他リージョンへのSpiderアクセスも速くなるかもしれません。それは今後の課題にしたいと思います。

以上です。