ヒマをみつけてWeb開発
その場の思い付きを、ヒマをみつけてWebサイトにしてみるブログ

Zookeeperメモ

Sunday, 16 May 2010 18:17 by sabro

Zookeeperが、けっこう独自ルール多いので、忘れないようにメモ。英語のドキュメント読んで理解してるから、間違ってる可能性あり。ちなみに、.NETドライバでの場合です。

  • Zookeeperクラスのインスタンスは、何度も使いまわすことが可能
  • Zookeeperクラスのコンストラクタに渡す、セッションタイムアウト値は、あくまでも一回の通信におけるタイムアウト値であって、Zookeeperインスタンスをタイムアウト値以上の時間保持しても、インスタンスが使えなくなることはない
  • Zookeeperクラスのコンストラクタに渡す、セッションタイムアウト値は、設定ファイルのtickTime値の2倍以上、20倍以下でないといけない
  • Zookeeperクラスのコンストラクタに渡すWatcherはデフォルトのウォッチャーであり、接続状態が変わる度にイベントが起こる、Zookeeperインスタンス生成時は、Connectionが非接続から接続に変わるので、いきなりイベント発生するので注意
  • Zookeeper.Exists、Zookeeper.GetData、Zookeeper.GetChildrenに渡すWatcherは観測対象のノードに変化があったときにイベント発生、イベントは1回しか起きない
  • 接続文字列には、複数のホストをカンマ区切りで指定可能、その場合は再接続のたびに適当に接続先を選んでくれる、またホストに接続出来なかった場合、別のホストへつないでくれる
  • クライアントアプリから接続後、クラスタを再起動しても、Zookeeperインスタンスを作りなおすことなく再接続できた、うまく再接続する仕組みになってるっぽい
  • Zookeeper.Deleteメソッドに渡すデータのバージョンは、-1を渡してやると、どんなバージョンでも削除してくれる、Zookeeper.SetDataのバージョンも同様
  • CreateModeで、PersistentSequentialや、EphemeralSequentialを指定すると、Node名の末尾に連番をつけてくれるが、これはNode名ごとではなく、ツリー全体で1つの連番を使う、"node1","node2"と作ったあとに"tmp3"を作ると、次は"node4"になる、普通アプリには複数の連番IDが必要なので、この機能で連番を作るのは厳しい

注意点も多いけど、再接続とかを、うまいことやってくれるのは、いい感じですね( ̄∇  ̄ )

Tags:   ,
Categories:   NoSQL
Actions:   Permalink | Comments (44) | Comment RSSRSS comment feed

Zookeeperを.NETから使ってみる

Thursday, 13 May 2010 15:11 by sabro

Cassandraemonの正式版はもう少しお待ちを。実際にうちのサービスに組み込んでみて、安定して動くことを確認してからリリースします。

で、今組み込み作業中なんですが、CassandraだとMySQLでやってた連番生成が出来ないことに気づきました。Diggは、ZooKeeperを使ってやってるみたいです。TwitterはMySQLなのかな。

Zookeeperは、分散システムを協調動作させるために、Hadoopチームによって作られたライブラリです。データ構造は、ファイルシステムのようなツリー構造になっていて、それぞれのノードに対して、アトミックで順序保証されたアクセスが可能とのこと。

でも、Zookeeperは今のところ正式なものとしては、Java、C言語しかインターフェースが用意されていません。一応Http Restでの呼び出しでZookeeperにアクセスできる実験的機能があるみたいですが、これはWatcherがJavascriptからしか使えないとか制限があるみたいですね。

これは諦めるしかないかなと思ってたんですが、調べてみると本家ZookeeperをForkして、.NETドライバを作ってる方がいました!

http://github.com/ewhauser/zookeeper

最終更新日が5月4日。まだ作ってる最中かもしれないですね。本家にマージされたりしないのかな( ̄∇  ̄ )

Gitでソース取ってきて、MonoDevelopで開いたところ、いくつかソースが足りません。どうやら、Antでソースを作る必要があるみたいなので、トップディレクトリでAnt実行。すると、無事ソースコードが作られてビルド成功しました(^^)

それでは、せっかくなんでC#で接続してみます。Zookeeperのインスタンスを作るには、IWatcherインターフェースを実装したクラスを自作しないといけないみたいなんで、適当にでっちあげます。(追記:Watcherが不要なら、Nullを渡してもいいみたいです)

public class DefaultWatcher : IWatcher
{
	public void Process (WatchedEvent @event)
	{
		Console.WriteLine(@event.Path);
		Console.WriteLine(@event.Type);
		Console.WriteLine(@event.State);
	}
}

最初は、ZNodeを作る例です。Zookeeperのコンストラクタには、接続ホスト名&ポート、セッションタイムアウト、でっちあげたWatcherを渡します。Createメソッドでは、ノードパス、格納データ、接続ACL、CreateModeを渡してます。接続ACLはいくつか定数で用意されてたので、そのまま使いました( ̄∇  ̄ )

using(var zookeeper = new ZooKeeper("RemoteLinuxServer:2181", 
                                    new TimeSpan(0,1,0), 
                                    new DefaultWatcher()))
{
	var response = zookeeper.Create("/node1", 
	                                Encoding.UTF8.GetBytes("data1"), 
	                                Ids.OPEN_ACL_UNSAFE,
	                                CreateMode.Persistent);
	                                

	Console.WriteLine("Create : " + response);
}

// ### result ###
// Create : /node1

接続先のLinuxサーバ側で確認してみると、ルートディレクトリに「node1」が作られていました。今度は、Linuxサーバ側で、node2を作ってみます。

[root@RemoteLinuxServer bin]# ./zkCli.sh -server 127.0.0.1:2181
[zk: 127.0.0.1:2181(CONNECTED) 1] ls /
[node1, zookeeper]
[zk: 127.0.0.1:2181(CONNECTED) 2] create /node2 data2
Created /node2

再び、C#に戻って、GetChildrenメソッドにパスと、Watchフラグを渡して実行。Linuxサーバ側で追加したnode2が取れてます。

using(var zookeeper = new ZooKeeper("RemoteLinuxServer:2181", 
                                    new TimeSpan(0,1,0), 
                                    new DefaultWatcher()))
{
	var responses = zookeeper.GetChildren("/", false);

	foreach(var res in responses)
	{
		Console.WriteLine("GetChildren : " + res);
	}
}

// ### result ###
// GetChildren : node2
// GetChildren : node1
// GetChildren : zookeeper

うーん、グッジョブと言わざるをえない。とりあえず、もうちょっといじってみたいと思います( ̄∇  ̄ )

Tags:   ,
Categories:   .NET | NoSQL
Actions:   Permalink | Comments (46) | Comment RSSRSS comment feed