RethinkDBとPostgreSQLの比較:私の個人的な経験より – 前編

導入

最初はRethinkDB社の業務停止 とRethinkDBのライセンスの状況(私の仕事のある部分を阻害するもの)が発端となり、Hacker Newsでのこのディスカッションに触発されたことで、RethinkDBの代わりにPostgreSQLを使いSageMathCloud(SMC)のリアルタイムとデータベースコンポーネントを全面的に書き直すために、2カ月間必死に働きました。2015年3月からRethinkDBを葛藤しながらも大いに使用していましたが、PostgreSQLも同様に活用しています。本番データを使い両システムで同じクエリを全て書き直しているので、私は自分の使い方のケース(SMCのサイト)を比較するのにちょうど良い立場にいるわけです。

これから話すのは私の経験です。”ベンチマーク”や再現可能なハードデータなどを含まない個人的な比較です。言うなれば、休憩所にいる時に話すような内容です。

概要:

  • 私はリライトに非常に満足しています。
  • 全てに関してRethinkDBよりもPostgreSQLを使うことの方が桁違いに効率的です。
  • RethinkDBよりもPostgreSQLを使ってデータの探索クエリを実行する方がはるかに簡単です。PostgreSQLはReQLよりも表現が豊かで膨大な数のビルトイン機能を備えています。そのため、私たちはデータをもっとうまく活用しています。RethinkDBでは、最新のデータベースのダンプを使ってグレップするだけで終わることが多かったです。
  • PostgreSQLは”静的型付け”であるのに対し、RethinkDBには型やスキーマの適用は全くありません。明示的でクリアな型付けはアプリケーションの質と信頼性を高めました。
  • CPUの数とディスク容量の要件を下げたことで、なんと月々$800(!)も節約できている。
  • RethinkDBが2017年2月にApacheのライセンスに変更されるとは、全く見当がつきませんでした。

数学者の弁明

この投稿によって、RethinkDBに関わる一部の人々をひどく怒らせてしまうかもしれません。

@williamstein RethinkDBコミュニティのプロジェクトの得策のため、そして特にコミュニティとexチームのメンバの努力に敬意を払ってくれるのであれば、コミュニティをこのように惑わすことはやめてください。

そして次のように続きます。

@williamstein 前回の投稿を削除してくれますか。

ユーザの声を無視することは、質の高いソフトウェアを作るための最適な方法ではないでしょう。Slavaのpostmortemにおいて彼は以下のように話しています。

人々は、私たちが提案した”現実世界”の作業負荷ではなく、彼らが実際に努力した作業負荷においてRethinkDBが高速に動くことを望んでいました。例えば、彼らは1万のドキュメントを逆方向に読み取ることなく挿入するのにどのくらい時間がかかるのか計るために、速く動くスクリプトを書くでしょう。MongoDBがこれらの作業負荷を極めていた一方で、私たちは市場に認められるために負け戦をしていたのです。
– Slavaのコメント

これまでSageMathを使い、多くの技術的な内容やそれ以外の内容の議論を激しく交わしてきましたが、壮大な討論は堂々巡りに終わっていました。私たちは設計上の選択を批判しないで欲しいなどとは言いません。Linuxのkernelは明らかに似ていますが、こちらは大きな成功を収めています。

このブログの投稿を書いている理由の一端は、私が今までRethinkDBの素晴らしい点をたくさん話してきたからです。実のところ、私はRethinkDBが解決した問題を気に入っており、Daniel Newesのような優秀なエンジニアが引き続きこのプロジェクトに専任で働いてくれていたら、RethinkDBは2、3年後まで続いただろうと信じています。私は特定のソフトウェアを使って解決した問題に対しては、さほど興味がありません。例えば、SMCの全てのコンポーネントは複数回にわたって書き直されており、何万行ものコードを無駄にしてきました。私が関心を持っているのはソリューションであって、特定のコードそれ自体を賛美しているわけではありません。そのような訳で、この投稿を書いているのです。

RethinkDBの未来について本当に真剣に考えている開発者たちがユーザの意見を聞くことを願っています。それゆえにこの投稿を正しく理解してくれるであろうことも。私はこういった発言をすることで嫌われる覚悟もできています。

リアルタイムWebアプリケーション

様々なアプローチを用いて”リアルタイム”Webアプリケーションを書くことができます。”リアルタイム”Webアプリケーションとはつまり、ユーザの操作に反応して素早くアップデートするアプリケーションを使い同時に複数のユーザが利用できるイベント駆動型アプリケーションのことです。React.jsについて学びReact.jsを使ってたくさんのSMCのフロントエンドを書き直した後、システム上の各コンポーネントが(データベースの)状態の変化をリッスンして反応する、似たような反応型のアーキテクチャをバックエンドで使いたいと思いました。2015年の初旬にはFacebookのGraphQLのようなものも欲しかったのですが、利用可能な実装はまだありませんでした。

RethinkDBはクライアントがデータベースへの状態の変化をリッスンして反応します。2015年には”実務に使える”と宣伝されたため、SMCがRethinkDBをバックエンドデータベースとして使うように、数カ月を費やしてSMCを書き直しました。それ以前はCassandraを使っていましたが、メモリ内のアプリケーションレベル(つまりデータベースは使っていません)において、全てのリアルタイム機能が出来上がった状態でデータベースを単純に利用していただけでした。アーキテクチャは機能していましたが、実装したい機能は広範にわたってありました。それにはこのアプローチでは不可能で、メッセージキューの導入が必須でした。また、Cassandraは私のデータには適合しなかったため、Datastaxの人々と電話で価格の話をするのは恐ろしいものでした。

2015年の夏はReactとRethinkDB上でSMCを再構築して過ごしました。基本的に2015年5月から2016年7月までの間、RethinkDBの書き直しに何カ月も苦労を重ねデバッグを行いました。いくつかのエッジケースにおいて、RethinkDBをクラッシュさせるだろう致命的なバグを見つけましたが、RethinkDBの開発者たちは常に修正してきました。また、手間のかかる拡張性とパフォーマンスの問題にも多数出くわしましたが、退屈なベンチマーク、デバッグ、ログの調査、そしてクライアント側の回避策(つまり、changefeedでのアイドルタイムアウト)を導入することによって修正しました。そして2016年7月には、RethinkDBをかなり安定して使えるようになりました。

2015年の夏にSMCで私と一緒に働いていたコンピュータ科学専攻のJonathan Leeという生徒が、パフォーマンスの問題があるのでRethinkDBを使わないように助言してきました。特に、RethinkDBが一貫してMongoDBよりも5~10倍動作が遅いというこの2015年のブログ投稿について指摘がありました。私はRethinkDBが1、2年もすれば遅れを取り戻すと信じていたので、Jonathanの助言を無視しました。実務に使えるようになったことで、ベンチマークのことを気にするようになると思ったのです。ですから自動フェイルオーバのバグを修正し、現在の機能を安定させるのに1年近くもかかるとは思いませんでした。本心では、Jonathanが正しくて自分が大きな間違いを犯しているという違和感があったのにも関わらず、私はそれを無視したのです。

あるRethinkDBの社員は、RethinkDBを強く推奨していた私をRethinkDBにとっての最大のユーザだと思っていたと話してくれました。

2016年7月までにRethinkDBを使い果たすのは辛いことでした。(およそ)10kのchangefeedからのロードを処理するために、RethinkDBノード内のCPUを何度も繰り返し確認したのを覚えています。私に必要だったのは単に”教養”で、RethinkDBを誤って使っていたのかもしれません。全ては戦いでした。バックアップをしようとすることすら非常に大変で、最終的には適切で整合性のあるフルバックアップを取得することを諦めました(代わりに完全なJSONダンプを介して本当に重要なテーブルのみバックアップを取っています)。また、ディスクの使用率についても多くの問題を抱えていました。

2016年7月頃、ついにRethinkDBを使い安定して機能するようにセットアップすることができました。DockerとKubernetesを使ったことでスケールアップ/ダウンを微調整しやすくなり、初めて良さが分かりました。また、Harald SchillyがRethinkDBの文書のこのセクションはそれに刺激をうけ、”RethinkDBのプロキシノード”を使うことを提案してきました。これらはどのようなデータもディスクに格納しないRethinkDBノードですが、しっかりchangefeedの処理を行います。

プロキシノードはいくつかのクエリの処理を自己で行うことができ、データベースサーバ上のCPUの読み込みを減らします。

最終的に、6つのノードのRethinkDBクラスタに加えて20のRethinkDBのプロキシ/WebサーバポッドをKubernetesクラスタに備えて稼働させたので、負荷を処理することができました。そういった時でさえも、プロキシノードはCPU使用率が比較的高い状態で稼働することが頻繁にあります。私にはその理由が全く解りませんでした。実際、SMCアーキテクチャ全体の中で理解出来なかったのは、唯一この高いCPU使用率だけでした。私は純粋な数学研究者という職業に就いており、オープンソースのソフトウェアの愛好者です。ですから、物事の仕組みの方法と理由を理解しようとすることに慣れているのですが、この点だけは全く理解ができませんでした。

RethinkDB社が業務を停止した当初、私たちのサイトは、前述した多くのノードで正常に動作していたこともあり(それに、この組織にどれだけのお金を費やした把握していなかったこともあり)、私は1~2年の間は少しじっとして、事の成り行きを見てみようと決めました。そして、それから少し経った後、将来的に重要となりそうな顧客と、オンプレミスのインストールに関して長く密度の濃い会議を行いました。先方の基本的な要望の1つは”スタックにAGPLがない”というものです。RethinkDB社がなくなった当時の状況下では、その要望に応えるのは不可能でしたし、私の望みも暗礁に乗り上げていました。

私の予想では、Daniel Mewesの集中的な取り組みの成果により、2017年の間にはスピードが大幅に向上するはずでした。しかし私の知る限り、彼はあまりRethinkDBには取り組まず、Stripeでフルタイムの仕事を始めたということです。また、ライセンスの状況が解決されないのではないかということも気掛かりでした(“ライセンスについて心配することを、PGはホームコメディー的(1)だと言います。重要な仕事をしてそうで、その実、何の変化も生み出しません”)。ただし現在では、ご存じのように解決されています

2016年12月初旬、私はもう十分だろうと判断し、PostgreSQLを代わりに使うため、CoffeeScriptで5600行になるRethinkのコードを書き直し始めました。最初の1週間で行ったのは、PostgreSQLのLISTEN/NOTIFY/TRIGGER機能を使ったプロトタイプとベンチマークの作成です。私にとって重要なのは、”クールな技術を使うこと”ではなく、”顧客の問題を解決できる技術を使うこと”です。LISTEN/NOTIFY/TRIGGERのレベルがどれだけ低かろうと、あるいはRethinkDBのchangefeedより多くの作業や思索が必要になろうと、最終結果さえよければ私は気にしません。

“会社がなくなった今、RethinkDBを使っているSageMathCloudのような製品は今後どうなるのだろう” – Hacker Newsのnchelluriのコメント