Galapagos Tech Blog

株式会社ガラパゴスのメンバーによる技術ブログです。

FoundationDBを試してみる

ご機嫌よう、ガラパゴスのおとめです。

先日のことですが、AppleがFoundationDBをオープンソースにしたというニュースが目に止まりました。そこでFoundationDB、て何かしらん、と調べてみたら、次のように魅力的なリストができました。

  • ACIDなNoSQL
  • SQLで操作可能
  • SSDを使う場合で、1コアで20,000書き込み/秒のスループット
  • 500コアまでリニアにスケール(1400万書き込み/秒までスケールするという記事もあり)
  • 読み込みは1ms、書き込みは5ms
  • キーはソートされている

そこで、まずは試してみることにしました。

インストールしてみる

とりあえず適当なUbuntu Server 16.04のVMに入れてみます(システム要件を満たしていないことは置いておきます)。まあ手順は公式に書いてある通りなのですが……

$ sudo dpkg -i foundationdb-server_5.1.5-1_amd64.deb
dpkg: 依存関係の問題により foundationdb-server の設定ができません:
 foundationdb-server は以下に依存 (depends) します: python (>= 2.6) ...しかし:
  パッケージ python はまだインストールされていません。

ここでガラパゴスのおとめはちょっとハマってしまいました。Ubuntu 16.04ではPython3.5が入っていて、コマンドもpython3だからなのかな? とか、python2も入れておいて、update-alternativesしないとダメなのかしらん? とか……

結論としては、sudo apt-get install pythonするだけでした。

インストールが済んだら確認してみます。

$ fdbcli
Using cluster file `/etc/foundationdb/fdb.cluster'.

The database is available.

Welcome to the fdbcli. For help, type `help'.
fdb>

次にbindingをインストールしてみましょう。この記事を書いている時点では、以下の言語が用意されています。

使ってみる

今回はRubyから使ってみます。公式のガイドでは何故かgemを直接ダウンロードするみたいに書かれていますが、gem install fdbで入ります。ダウンロードしたgemを使う場合は、ffiに依存していますので一緒に入れると良いでしょう。

では早速公式のAPIリファレンスとにらめっこしつつREPLから使ってみます(Ruby 2.5.1から使っているので時々ワーニングが出ています)。

$ irb
irb(main):001:0> require 'fdb'
=> true
irb(main):002:0> FDB.api_version 510
/home/his/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/fdb-5.1.5/lib/fdbimpl.rb:173: warning: constant ::Fixnum is deprecated
/home/his/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/fdb-5.1.5/lib/fdbimpl.rb:173: warning: constant ::Fixnum is deprecated
/home/his/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/fdb-5.1.5/lib/fdbimpl.rb:173: warning: constant ::Fixnum is deprecated
=> nil
irb(main):003:0> db = FDB.open
=> #<FDB::Database:0x000056493f1fb808 @dpointer=#<FFI::Pointer address=0x00007f4ddc001050>, @options=#<FDB::DatabaseOptions:0x000056493f1fb790 @setfunc=#<Proc:0x000056493f1fb7b8@/home/his/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/fdb-5.1.5/lib/fdbimpl.rb:553 (lambda)>>>

……ここいらへんから既に公式のリファレンスが何を言っているのかわかりません。というかAPIの説明が何もないので、ソースコードの方を見てみると、どうやらFDB.openの戻りを使ってget/set/clearすることでKVSのように使えるようです。

irb(main):004:0> db.set(1, 'foo')
Traceback (most recent call last):
        6: from /home/his/.rbenv/versions/2.5.1/bin/irb:11:in `<main>'
        5: from (irb):8
        4: from /home/his/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/fdb-5.1.5/lib/fdbimpl.rb:581:in `set'
        3: from /home/his/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/fdb-5.1.5/lib/fdbimpl.rb:569:in `transact'
        2: from /home/his/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/fdb-5.1.5/lib/fdbimpl.rb:582:in `block in set'
        1: from /home/his/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/fdb-5.1.5/lib/fdbimpl.rb:877:in `set'
NoMethodError (undefined method `bytesize' for 1:Integer)

何か怒られました。Integer#bytesizeが存在しないと言われています。bytesize? じゃ文字列を入れてみたらいいのかしらん?

irb(main):005:0> db.set('1', 'foo')
=> "foo"
irb(main):006:0> db.get('1')
=> "foo"

何か入ったようです。試しにFDBコンソールから確認してみましょう。するとこのようにちゃんと登録されているようです。

$ fdbcli
Using cluster file `/etc/foundationdb/fdb.cluster'.

The database is available.

Welcome to the fdbcli. For help, type `help'.
fdb> get 1
`1' is `foo'

では何件か登録してみます。

irb(main):007:0> db.set('100', 'bar')
=> "bar"
irb(main):008:0> db.set('30', 'baz')
=> "baz"

既存のキーを書き換えてみます。

irb(main):009:0> db.set('1', 'hmm')
=> "hmm"

ところでキーは必ずソートされていると書かれていました。確認してみましょう。キーを複数取得するには、get_rangeを使うと良さそうです。

irb(main):010:0> db.get_range('1','100')
=> [#<FDB::KeyValue:0x000056493ee77970 @key="1", @value="hmm">]
irb(main):011:0> db.get_range('1','999')
=> [#<FDB::KeyValue:0x000056493eb7e520 @key="1", @value="hmm">, #<FDB::KeyValue:0x000056493eb7e160 @key="100", @value="bar">, #<FDB::KeyValue:0x000056493eb7d788 @key="30", @value="baz">]

ふむ。(とりあえずデフォルトでは)ソート順はCなのかしらん? そして、get_rangeの引数に与えるキーの範囲ですが、始点は含んで終点は含まないことが分かりました。ためしにFDBコンソールからも見てみましょう。

fdb> getrange 1 999

Range limited to 25 keys
`1' is `hmm'
`100' is `bar'
`30' is `baz'

ソートされているようです。

さて、今回はFoundationDBのさわりとして、RubyからかあるくKVS風に触ってみました。SQLで操作とかトランザクションとかスループットとかも多いに気になるところですが、今回はここまでにしましょう。スループットとかはErlangで10,000プロセスくらいで一気に書いてみたらいいのかしらん……?


ところでガラパゴスではエンジニアを募集しています。ご興味をお持ちの方はぜひ弊社の採用ページをご覧ください。

www.glpgs.com

では、ご機嫌よう。

--

この記事は業務の一環として業務時間中に書きました