まだ道半ばなんだけど、GroongaをGo+Perlなフロントエンドから使うシステムを動かしはじめている。
今回はとりあえず現時点での状態をざっくり書き出してみる。まだ本番化はしてないが、とりあえず本番環境からデータの挿入・削除ができるところまでつなぎ込みはした。最終的に全面的に本番化したらまたまとめ直します。
まずデータを突っ込む部分は慣れもあるのでより素早くデータの整形をしたりテーブルスキーマとかを変更したりするためにPerlでワーカーをさくさくっと書いた。ワーカーはQ4Mでデータを受け取り、データを整形してMroonga経由でデータを挿入。仕組みができたところでGroongaが我々が求めているデータ量をハンドリングできるかどうか検証するために全力で平均1行4KB~10KBくらいのデータをmroonga経由で○億件挿入してみた。この挿入処理中様々な地雷を踏んだので、kazeburoさんの助言などを元に挿入先のDBとテーブルをshardingしたりしてそれらを回避。
データは二つのよさげな検証用マシンにそれぞれ5000万件のところまではO(log(N))的な感じで挿入できていたが、それ以降は線形。これを書いている時点で1日約600万件の挿入ができている。5000万件の時点で関連grnファイルを全てあわせるとそれぞれのマシンに360GBずつそのあとはだいたい1日100GBずつくらい増えている。
sharding部分が落ち着いてきたら次は既存のシステムへのつなぎ込み用HTTP APIを作成。ここを今回はGoで作成。Goの部分は 練習もあったので簡単な参照部分をまずストレートなHTTP APIハンドラとして実装してみた。ステートレスなのでstructとかは基本的に作らず、golang.orgのExampleをほぼそのまま。
参照部分でどれだけ性能が出るのかどきどきだったけど、全く問題なし。Goちゃん速い。
次にデータ挿入部分はすでに生成してあるPerl製ワーカーとのつなぎこみだけなんだけど、queueへの書き込み部分はDBへの接続と使用テーブル両方ともある程度ランダムにばらしているのでその部分は全部Goで書き直し。この時点でサーバー側でステートを持ち始める必要ができてきたので、ApiServer型を作ってHTTPハンドラはクロージャで登録するような形に変更。コード的にはこれが大分おおきな変更だったけど、手を動かせばいいだけで、別にはまるところはなかった。定期的にランダムに挿入先をリフレッシュするように書いたんだけど、ここもgoroutineを使ってきれいにできた。time.Ticker便利!シグナル処理部分で一瞬迷ったけど、Perl5のSafe Signalsと同じ仕組みをchannelで実装しているだけだとわかってしまえばあとは簡単だったので、ごにょごにょしたり、一旦握りつぶしたシグナルをsyscall.Kill()でまた流したりとか色々した。
というわけで良い感じになってきた。そのうちこのシステムも皆様が触る部分にお目見えできると思っております。
今回はとりあえず現時点での状態をざっくり書き出してみる。まだ本番化はしてないが、とりあえず本番環境からデータの挿入・削除ができるところまでつなぎ込みはした。最終的に全面的に本番化したらまたまとめ直します。
まずデータを突っ込む部分は慣れもあるのでより素早くデータの整形をしたりテーブルスキーマとかを変更したりするためにPerlでワーカーをさくさくっと書いた。ワーカーはQ4Mでデータを受け取り、データを整形してMroonga経由でデータを挿入。仕組みができたところでGroongaが我々が求めているデータ量をハンドリングできるかどうか検証するために全力で平均1行4KB~10KBくらいのデータをmroonga経由で○億件挿入してみた。この挿入処理中様々な地雷を踏んだので、kazeburoさんの助言などを元に挿入先のDBとテーブルをshardingしたりしてそれらを回避。
データは二つのよさげな検証用マシンにそれぞれ5000万件のところまではO(log(N))的な感じで挿入できていたが、それ以降は線形。これを書いている時点で1日約600万件の挿入ができている。5000万件の時点で関連grnファイルを全てあわせるとそれぞれのマシンに360GBずつそのあとはだいたい1日100GBずつくらい増えている。
sharding部分が落ち着いてきたら次は既存のシステムへのつなぎ込み用HTTP APIを作成。ここを今回はGoで作成。Goの部分は 練習もあったので簡単な参照部分をまずストレートなHTTP APIハンドラとして実装してみた。ステートレスなのでstructとかは基本的に作らず、golang.orgのExampleをほぼそのまま。
参照部分でどれだけ性能が出るのかどきどきだったけど、全く問題なし。Goちゃん速い。
次にデータ挿入部分はすでに生成してあるPerl製ワーカーとのつなぎこみだけなんだけど、queueへの書き込み部分はDBへの接続と使用テーブル両方ともある程度ランダムにばらしているのでその部分は全部Goで書き直し。この時点でサーバー側でステートを持ち始める必要ができてきたので、ApiServer型を作ってHTTPハンドラはクロージャで登録するような形に変更。コード的にはこれが大分おおきな変更だったけど、手を動かせばいいだけで、別にはまるところはなかった。定期的にランダムに挿入先をリフレッシュするように書いたんだけど、ここもgoroutineを使ってきれいにできた。time.Ticker便利!シグナル処理部分で一瞬迷ったけど、Perl5のSafe Signalsと同じ仕組みをchannelで実装しているだけだとわかってしまえばあとは簡単だったので、ごにょごにょしたり、一旦握りつぶしたシグナルをsyscall.Kill()でまた流したりとか色々した。
というわけで良い感じになってきた。そのうちこのシステムも皆様が触る部分にお目見えできると思っております。