読者です 読者をやめる 読者になる 読者になる

Rowzと戯れる

gizzard Python Thirft

gizzardやgizzardの使用例のRowzが気になっていても、ビルドに失敗することが多く手を出せないでいた。最近、だいぶScalaの勘所がつかめてきて、ようやく自分で試してみることができるようになったので、そのメモ。

Rowzのテストは通らないような気がするので、skip.testでテストを省略してビルドする。

$ git clone git://github.com/nkallen/Rowz.git
$ cd Rowz
$ ant dist -DDB_USERNAME=scott -DDB_PASSWORD=tiger -Dskip.test=1

MySQLにrowz_nameserverというテーブルを作ったうえで、rowzを起動。

$ ./bin/rowz scott

Rowzにサンプルスクリプトがあるので動かしてみる。

$ ./src/scripts/gzr.rb

他の言語でアクセスするには、src/main/thrift/Rowz.thriftからThriftクライアントを生成する。Pythonならば、

$ thrift --gen:py src/main/thrift/Rowz.thrift

でクライアントを生成し、gen-pyディレクトリにパスを通しておく。あるいはgen-pyの中のRowzモジュールをsite-packagesにコピーする。

Rowzに含まれているサンプルのRubyスクリプトと同じことをするPythonスクリプト。

import time

from thrift.transport import TTransport
from thrift.transport import TSocket
from thrift.protocol import TBinaryProtocol

from Rowz import Rowz

socket    = TSocket.TSocket('127.0.0.1', 7919)
transport = TTransport.TBufferedTransport(socket)
protocol  = TBinaryProtocol.TBinaryProtocol(transport)

client = Rowz.Client(protocol)
transport.open()

for x in xrange(1, 10):
    object_id = client.create("row %d" % x, int(time.time()))
    time.sleep(1)
    print client.read(object_id)

ShardやForwardingの設定もThrift経由で出来るが、Rowzのgizzardのバージョンが古いので注意が必要。gizzardのこのcommit以前のThrift Interfaceからクライアントを生成しなくてはいけない。一応、Python版をはっておくと、以下のような感じ。

import sys
import time

from thrift.transport import TTransport
from thrift.transport import TSocket
from thrift.protocol import TBinaryProtocol

from ShardManager import ShardManager
from ShardManager.ttypes import ShardInfo, Forwarding

socket    = TSocket.TSocket('127.0.0.1', 7920)
transport = TTransport.TBufferedTransport(socket)
protocol  = TBinaryProtocol.TBinaryProtocol(transport)

manager = ShardManager.Client(protocol)
transport.open()

PARTITIONS = 10
KEYSPACE   = sys.maxint

for x in xrange(1, PARTITIONS + 1):
    shard_info_a = ShardInfo(
        class_name="com.twitter.rowz.SqlShard",
        table_prefix="data_a%s" % x,
        hostname="127.0.0.1",
        source_type="",
        destination_type="",
        busy=0)
    id_a = manager.create_shard(shard_info_a)

    shard_info_b = ShardInfo(
        class_name="com.twitter.rowz.SqlShard",
        table_prefix="data_b%s" % x,
        hostname="127.0.0.1",
        source_type="",
        destination_type="",
        busy=0)
    id_b = manager.create_shard(shard_info_b)

    replication_shard_info = ShardInfo(
        class_name="com.twitter.gizzard.shards.ReplicatingShard",
        table_prefix="replicating_%s" % x,
        hostname="127.0.0.1",
        source_type="",
        destination_type="",
        busy=0)
    id_repl = manager.create_shard(replication_shard_info)

    manager.add_child_shard(parent_shard_id=id_repl, child_shard_id=id_a, weight=1)
    manager.add_child_shard(parent_shard_id=id_repl, child_shard_id=id_b, weight=1)

    lower_bound = KEYSPACE / PARTITIONS * x
    manager.set_forwarding(Forwarding(base_id=lower_bound, shard_id=id_repl))

manager.reload_forwardings()

Rubyはアレだから好きじゃないし、ScalaRuby臭がするからどうかと思うけどScala, Rubyの研鑽が不足しているからgizzardの構造がよく分からなかったけど、見通しをつける最初の関門はクリアした気がする。