まだプログラマーですが何か?

プログラマーネタとアスリートネタ中心。たまに作成したウェブサービス関連の話も http://twitter.com/dotnsf

NoSQL データベースの1つで、非構造データを JSON 形式で保持できる mongoDB を「レプリカセット」と呼ばれる方法でクラスタリングします。

今回は3台の CentOS マシンによるクラスタ構成を行います。1台がプライマリ、1台がスレーブ、そして1台がアービターと呼ばれるフェイルオーバー時のマスター選択専用ノード(データは保持しない)で構成します。


プライマリ/スレーブ/アービターそれぞれのマシンの IP アドレスは P.P.P.P / S.S.S.S / A.A.A.A であると仮定して以下を記載します。


まず、3台のマシンそれぞれに MongoDB をインストールします。MongoDB の導入手順にそのものについては以下を参照してください:
mongoDB を CentOS 上にインストールする

上記手順最後のコマンド "chkconfig mongod on" までが実行されていれば、3台のマシン上それぞれで MongoDB が(独立して)稼働している状態になっています。


ここからがレプリカセット環境構築のための設定になります。まずそれぞれのマシン上で /etc/mongod.conf を編集します。編集内容は2点で (1) bind_ip 行をコメントアウト、 (2) replSet 行を追加 します:
# vi /etc/mongod.conf
  :
  :
# bind_ip=127.0.0.1 (コメントアウト)
  :
  :
replSet=testRS (この1行を追加)
  :
  :
なお、replSet=XXX で追加する行の XXX 部分は同じ文字列(上記例では testRS )を指定します。これによって3台の mongoDB サーガーが同一のレプリカセット環境上にあることを指定します。

bind_ip 行は接続を受け付ける元のアドレス範囲を指定する行です。127.0.0.1 が指定されていると localhost のみが指定されたことになり、他のマシンからの接続を受け付けなくなってしまうのでコメントアウトします。

ここまで出来た所で、3台のマシンそれぞれで mongoDB を再起動します:
# /etc/init.d/mongod restart


次にプライマリサーバー(P.P.P.P) 上で、各マシンの役割を指定します。プライマリサーバー上でコンソールにログインします:
# mongo

> 

コンソール画面内で以下を実行します:
> config = { _id:"testRS", 
  members:[
    { _id:0, host:"A.A.A.A:27017", arbiterOnly:true }, 
    { _id:1, host:"P.P.P.P:27017" },
    { _id:2, host:"S.S.S.S:27017" }
  ]
}
 :
:
> rs.initiate( config ) :
:
>

上記コマンドで testRS(replSet に指定した文字列値)に属する3台のマシンの IP アドレスとポート番号を指定し、A.A.A.A のマシンについてはアービターのノードであることも指示しています。 そしてその内容を rs.initiate コマンドで実行して初期化しています。

これが成功するとレプリカセットの完成です。rs.status() コマンドでレプリカセットの設定状況を確認することもできます:
> rs.status()
{
  "set": "testRS",
  "date": ISODate("2014-06-02T12:34:56Z"),
  "myState": 1,
  "members": [
    {
      "_id": 0,
      "name": "A.A.A.A:27017",
      "health": 1,
      "state": 7,
      "stateStr": "ARBITER",
      "uptime": 30,
      "lastHeartbeat": ISODate("2014-06-02T12:34:56Z"),
      "pingMs": 1
    },
    {
      "_id": 1,
      "name": "P.P.P.P:27017",
      "health": 1,
      "state": 1,
      "stateStr": "PRIMARY",
      "uptime": 80,
      "optime": Timestamp(1357209986000, 1),
      "optimeDate" : ISODate("2014-06-02T12:34:56Z"),
      "self": true
    },
    {
      "_id": 2,
      "name": "S.S.S.S:27017",
      "health": 1,
      "state": 2,
      "stateStr": "SECONDARY",
      "uptime": 30,
      "optime": Timestamp(1357209986000, 1),
      "optimeDate" : ISODate("2014-06-02T12:34:56Z"),
      "lastHeartbeat": ISODate("2014-06-02T12:34:56Z"),
      "pingMs": 1
    }
  ],
  "ok": 1 
}

> 

_id = 0 のマシンがアービター、1 のマシンがプライマリ、2 のマシンがスレーブになっていることを確認します。


一応これでレプリカセット環境としては動くようになりました。が、このままだとスレーブサーバーはプライマリサーバー以外のマシンからの接続を許可しないため色々不便です。というわけで、最後にスレーブサーバーにプライバリサーバー以外からも接続できるよう設定します。

スレーブサーバー上でコンソールにログインし、db.getMongo().setSlaveOk() コマンドを実行します:
# mongo

> db.getMongo().setSlaveOk()

>

これでスレーブサーバーに他のマシンから接続して状況を確認することもできるようになりました。




2台の CentOS サーバーで MySQL クラスタ環境を構築する機会があったので、その作業メモです。


前提条件として、2台の CentOS 6.5(x64_86) をそれぞれ A, B とします。それぞれの IP アドレスを AAA.AAA.AAA.AAA / BBB.BBB.BBB.BBB とします。これらにそれぞれ MySQL のデータノードと SQL ノードを構築します。A, B には MySQL 関連モジュールの導入は一切行っていないものとします。
なおサーバー A は管理ノードを兼ねることにします。以下の手順は2台構成ですが、3台目以降を追加する場合は B と同じ手順を行うことになります。

【手順1 MySQL Cluster をインストール(A, B)】
A/B 両方のサーバーに MySQL Cluster をインストールします。CentOS 6.x では MySQL Cluster は標準の yum リポジトリには含まれていないようなので、公式サイトからソースをダウンロードしてインストールします:
Download MySQL Cluster

上記サイトから最新版のインストールセットをダウンロードします。今回の前提環境(CentOS 6.5 64bit)であれば Platform に "Linux Generic" を選択して 64bit 版のモジュールファイルをダウンロードします(ダウンロード時に Oracle のアカウントが必要になります):
2014052801

ちなみに 2014/05/28 現在、この方法で取得すると MySQL Cluster 7.3.5(ファイル名 mysql-cluster-gpl-7.3.5-linux-glibc2.5-x86_64.tar.gz)がダウンロードできます。以下、このモジュールを使っている前提で記載を続けます。バージョン差異などでファイル名が異なる場合は適宜読み替えてください。

ダウンロードしたモジュールファイルを A, B 両方にコピーします(/tmp にコピーしたと仮定します)。そして以下の導入作業を A, B 双方で行います。

サーバーに root でログインし、まず mysql 用のユーザーとグループを作成します:
# groupadd mysql
# useradd -g mysql mysql

コピーした MySQL Cluster インストールモジュールを /usr/local/ 以下に展開し、mysql という名称でアクセスできるようにシンボリックリンクを張ります:
# cd /usr/local
# tar xzvf /tmp/mysql-cluster-gpl-7.3.5-linux-glibc2.5-x86_64.tar.gz
# ln -s mysql-cluster-gpl-7.3.5-linux-glibc2.5-x86_64 mysql

ファイルオーナーとファイルグループを変更します:
# chown -R root.mysql mysql-cluster-gpl-7.3.5-linux-glibc2.5-x86_64
# chown -R mysql.mysql mysql/data/

/usr/local/mysql/bin に PATH を通します:
(例)こういう結果になるよう ~/.bash_profile を編集する
# cat ~/.bash_profile
  :
  :
PATH=$PATH:$HOME/bin:/usr/local/mysql/bin
  :
  :

MySQL の管理用データベースを初期化して、デーモン起動用スクリプトをコピーして用意します:
# cd /usr/local/mysql
# ./scripts/mysql_install_db --user=mysql
# cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysql
# chown root.root /etc/init.d/mysql
# chmod u+x /etc/init.d/mysql

これでモジュールの導入は完了です、意外と簡単。この処理は全てのサーバー(今回の例であれば A と B)に対して行います。


管理ノードではないサーバー(B) のみ、/var/lib/mysql-cluster/ というフォルダを作成しておきます。中身は不要ですが MySQL が利用するのでファイルオーナーとグループオーナーを変更しておきます:
# mkdir /var/lib/mysql-cluster
# chown -R mysql.mysql /var/lib/mysql-cluster

管理ノードサーバー(A) に関しては、この作業は次の手順の中に含まれているので不要です。


【手順2 MySQL Cluster 管理ノードの設定(Aのみ)】
次に管理ノードの設定を行います。この作業はサーバー A に対してのみ行います。

今回は設定ファイルを /var/lib/mysql-cluster/ 以下に作成します。場所は任意で構いませんが、変更する場合は適宜読み替えてください。
# mkdir /var/lib/mysql-cluster
# chown -R mysql.mysql /var/lib/mysql-cluster
# vi /var/lib/mysql-cluster/config.ini
  :
  :
[NDB_MGMD]
hostname=AAA.AAA.AAA.AAA  # 管理サーバー(サーバーA)のIPアドレス

[NDBD default]
NoOfReplicas=2  # クラスタ環境の冗長化数(台数)
datadir=/var/lib/mysql-cluster

[NDBD]
hostname=AAA.AAA.AAA.AAA  # 1台目のデータノードの IP アドレス
datadir=/var/lib/mysql-cluster

[NDBD]
hostname=BBB.BBB.BBB.BBB  # 2台目のデータノードの IP アドレス
datadir=/var/lib/mysql-cluster

[MYSQLD]
hostname=AAA.AAA.AAA.AAA  # 1台目のSQLノードの IP アドレス

[MYSQLD]
hostname=BBB.BBB.BBB.BBB  # 2台目のSQLノードの IP アドレス


【手順3 MySQL Cluster SQL ノードの設定(A, B)】
次にSQLノードの設定を行います。この作業はサーバー A, B 両方に対して行います。

具体的には /etc/my.cnf をクラスタ環境向けに編集します:
# vi /etc/my.cnf
  :
  :
[mysqld]
ndbcluster
character-set-server=utf8

[mysql]
default-character-set=utf8

[mysql-cluster]
ndb_connectstring=AAA.AAA.AAA.AAA

[ndb_mgmd]
config_file=/var/lib/mysql-cluster/config.ini


【手順4 MySQL Cluster の起動(A, B)】
ここまでの作業で MySQL Cluster が起動できるようになっています。ただ MySQL Cluster を起動する際の注意点として、起動する時の順序は必ず以下の順番で行う必要があります。また停止は逆の順序で行う必要があります:
(1) 管理ノード起動(A)
(2) データノード起動(A, B)
(3) SQL ノード起動(A, B)

具体的には以下の様なオペレーションで MySQL Cluster を起動します:
管理ノード起動(A)
# cd /var/lib/mysql-cluster # ndb_mgmd
(起動メッセージが表示される。管理ノードがSQLノードを兼ねている場合は警告が表示されるが無視)

データノード起動(A, B)
# ndbd

SQLノード起動(A, B) # /etc/init.d/mysql start

この段階でサーバー A, B 双方で MySQL サーバーが起動して、それらはクラスタリング構成になっています。そのことを管理ノード A から ndb_mgm を実行後のプロンプトから show コマンドで確認してみます:
# ndb_mgm
-- NDB Cluster -- Management Client --
ndb_mgm> show
Connected to Management Server at: AAA.AAA.AAA.AAA:1186 管理ノード
Cluster Configuration
 ---------------------
[ndbd(NDB)]     2 node(s)
id=2    @AAA.AAA.AAA.AAA  (mysql-5.6.17 ndb-7.3.5, Nodegroup: 0, *) データノード(マスター)
id=3    @BBB.BBB.BBB.BBB  (mysql-5.6.17 ndb-7.3.5, Nodegroup: 0) データノード

[ndb_mgmd(MGM)] 1 node(s)
id=1    @AAA.AAA.AAA.AAA  (mysql-5.6.17 ndb-7.3.5) 管理ノード

[mysqld(API)]   2 node(s)
id=4    @AAA.AAA.AAA.AAA  (mysql-5.6.17 ndb-7.3.5) SQLノード
id=5    @BBB.BBB.BBB.BBB  (mysql-5.6.17 ndb-7.3.5) SQLノード

ndb_mgm>

こんな感じになっていれば正しくクラスタリングできています。


【手順5 MySQL ユーザーやデータベースの設定(A, B)】
MySQL Cluster では対象のデータベースの同期が取られますが、同期が取られないデータもあります。それらは個別に生成/設定する必要があります:
root ユーザーパスワード設定(A, B)
# mysql -u root
mysql> set password for root@localhost=PASSWORD('XXXXXXXX');

データベース作成(A) これは B に同期される
mysql> create database testdb default character set utf8;

データベースユーザー作成(A, B)
mysql> grant all privileges on testdb.* to test_user@localhost identified by 'test_pass'; 

そして改めて A で作成したデータベース testdb が B に同期されていることを確認します:
test_user ユーザーで testdb にログイン(B)
# mysql -u test_user -ptest_pass testdb
mysql> Bでは作成していないデータベースにログインできた!

※B での mysql コマンドでソケットファイルのエラーが表示される場合は
# mysql -u test_user -ptest_pass testdb --socket=/tmp/mysql.sock
といった感じで、ソケットファイルのパスを指定して実行する必要があります。


【手順6 データの同期を確認(A, B)】
最後に A で作成したテーブルやデータが B に同期されることを確認します。まずはクラスタ対応のテーブルを作成します:
(サーバー A で作業)
# mysql -u test_user -ptest_pass testdb
mysql> create table testtbl(n int) engine=ndbcluster; mysql> show table status *************************** 1. row *************************** Name: testtbl Engine: ndbcluster Version: 10 : :
mysql>

このテーブルに適当にデータを入れておきます:
(サーバー A で作業)
mysql> insert into testtbl values (123); mysql> select * from testtbl; +------+ | n | +------+ | 123 | +------+

このテーブルとデータがサーバー B にも同期されていることを確認します:
(サーバー B で作業)
# mysql -u test_user -ptest_pass testdb (--socket=/tmp/mysql.sock) mysql> select * from testtbl; +------+ | n | +------+ | 123 | +------+

無事、データの同期もできていることが確認できました。





先日の IBM XCITE イベントの中で、IBM BlueMix のアプリケーション開発コンテストの開催が発表されています:
IBM BlueMix Challenge
2014052501



このブログでも何度か触れてきましたが、IBM BlueMix は、いわば「IBM 版 CloudFoundry」です。IBM の提供するクラウド上に CloudFoundry 環境が構築されており、現在は無料ベータ版という扱いで誰でも利用することができるようになっています。素の CloudFoundry と異なるのは IBM ソフトウェア製品も利用可能なサービスとして統合されているので、BlueMix 上で Java アプリケーションサーバーや DB2 を始めとするデータベースサーバーなども利用できるようになっている点です。BlueMix 上で稼働する IBM 製品については原則的に IBM からの製品サポートが提供され、それ以外のものについても一部はサードパーティからの製品サポートが提供される、という形態になっています。

この BlueMix 環境上でアプリケーションを開発/構築するというコンテストです。なお、コードそのものの良し悪しだけで判断されるわけではなく、用意されたサービスをどのように組み合わせて、どのようなイノベーションを実現するか、という総合的な判断に基づくコンテストのようです。

気になる商品は Mac Book Pro やルンバといった、デベロッパー(やその家族)が喜びそうなものが用意されています。実際にはこれらの中でも上位機種が準備されているとの噂も・・・


参加する場合、6月30日までにそのための登録申請を行う必要があります。アプリケーションそのものは申請の段階で開発されている必要はなく、アプリケーションの提出期限は8月12日となっているようです。


注目の PaaS 環境である Cloud Foundry のアプリケーションを開発するいい勉強の機会にもなるし、あわよくば Mac Book Pro も手に入れるチャンスです。普通にアプリを開発できれば BlueMix(Cloud Foundry)対応はさほどハードルが高いとは思わないので、多くの開発者にチャンスがあると思います。


「興味はあるけど、まだあまりよく BluxMix(Cloud Foundry) 分からないんだよなあ・・・」という方は、拙作ですが、以下の僕のブログエントリがお役に立てれば幸いです:

- BlueMix を使う
- BlueMix のダッシュボードとデータベースサービスを使う
- BlueMix 上で PHP アプリを動かす
- BlueMix を使ってみて
- BlueMix で Twilio を使う
- BlueMix 向けに(Java)アプリを開発するといいことはあるか?
- BlueMix 向け Twilio アプリのサンプル
- BlueMix 開発コンテストが開催されるらしい
- BlueMix のデータストア比較
- BlueMix の cf コマンド
- BlueMix 上の DB2 をハック
- MySQL が 3306 番以外のポートで動いている時の WordPress 設定
- モバイル向けdeveloperWorks ページを作ってみた





 

このページのトップヘ