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

54行で分散KVSを実装する(レプリケーション機能付き)

Ruby と MessagePack-RPC があれば、簡単なkey-valueストレージは簡単に作れます。54行で書けます(レプリケーションと負荷分散機能付き。サーバー38行、クライアント16行)。
簡単なKVSをベースにして、ログ集計や遠隔デプロイ、遠隔管理機能などの機能を追加していけば、ちょっと便利なサーバープログラムをサクサク自作できるハズ。


この分散KVSは、(keyのハッシュ値 % サーバーの台数)番目のサーバーにkeyを保存します。また、サーバーの名前順でソートしたときの「次のサーバー」と「次の次のサーバー」にデータをレプリケーションします。

すべてのサーバーで同じ設定ファイルを使います。サーバーごとの設定は引数を自分のホスト名に書き換えるだけなので、デプロイが容易です。


MessagePack-RPC for Ruby を使うと、分散しないkey-valueストレージ*1は以下のように書けます:

require 'msgpack/rpc'

class KVServer
  def initialize
    @hash = {}
  end

  def get(key)   # publicなメソッドがRPCで呼べるようになる!
    @hash[key] # @hashからkeyを取り出して返す
  end

  def set(key, value)
    @hash[key] = value  # @hashにkey-valueをセット
  end
end

# MessagePack::RPC::Server#listen(アドレス, ポート番号, インスタンス)
svr = MessagePack::RPC::Server.new
svr.listen('0.0.0.0', '3030', KVServer.new)
svr.run   # イベントループ開始

と、20行足らずで実装できます。


クライアントは以下のようになります:

require 'msgpack/rpc'

cli = MessagePack::RPC::Client.new('127.0.0.1', 3030)
cli.timeout = 5   # 5秒でタイムアウトするように

# MessagePack::RPC::Client#call(メソッド, 引数...)
cli.call(:set, "key1", "val1")
puts cli.call(:get, "key1")


このコードにレプリケーションと負荷分散の機能を追加すると、githubにあるソースコードのようになります:http://github.com/frsyuki/simple-kvs


コマンド1発でサーバー群を起動 & テストできるようになっているので、実際に動かしてみます:

$ gem install msgpack-rpc    # MessagePack-RPC ライブラリ
$ gem install chukan    # 分散テストを自動化するライブラリ

$ git clone git://github.com/frsyuki/simple-kvs.git && cd simple-kvs
$ ./test.rb    # 自動テスト開始


MessagePack-RPC for Ruby で作る分散KVSでした。

*1:「分散KVS」は「書き込みの性能がスケールアウトするKVS」を意図しています。