BT

Datomicのアーキテクチャ

| 作者 Rich Hickey フォローする 54 人のフォロワー , 翻訳者 徳武 聡 フォローする 1 人のフォロワー 投稿日 2012年11月18日. 推定読書時間: 13 分 |

原文(投稿日:2012/11/02)へのリンク

Datomicはシンプルなサービスで組み立てられた新しいデータベースです。従来のRDBMSの機能性と新世代の分散ストレージシステムの柔軟なスケーラビリティのバランスを取ろうとしています。

動機

Datomicは次のゴールを目指しています。

  • 堅牢な情報モデルの提供。更新をしない
  • 冗長でスケーラブルなストレージシステムの利用
  • ACIDトランザクションと一貫性の提供
  • アプリケーションでの宣言的なデータプログラミング

どのようなデータベースにもサポートするデータモデルに対する考え方が必要です。従来のRDBMSは関係モデルにある種の更新のセマンティックを組み合わせたモデルをサポートします。一方、対極にある新しいNoSQLは自らが扱う情報についてほとんど何も知らず、キーによってBLOBを保持するだけで、結果の一貫性を保証します。Datomicはデータベースは情報システムであるべきだと考えます。情報は事実の集合であり、事実は起こったことです。過去は変えられませんので、データベースは事実を蓄積します。更新はしません。過去は忘れられることがあるかもしれませんが、変わりません。例えば、誰かが住所を'変更'したなら、Datomicに保存されるのは、新しい住所を手に入れたという事実であり、過去の事実は置き換えられません。この不変性は多くの重要な設計上の利点と機会を提供します。

高い可用性を持ち、冗長で分散されているスケーラブルなストレージシステムの世界ではAmazonのDynamoのような素晴らしい進歩がありました。一枚岩の設計から遠ざかる中で、Datomicはこのようなシステムを直接的にサポートし、ストレージシステムやロケーション、コストやスケーラビリティなどの特性をユーザが選べるようにしようと模索しています。

ACIDトランザクションは多くのビジネスプロセスで極めて重要です。ACIDのスケーリングの難しさ起因する問題は多いですが、Datomicはトランザクションを読み取り/問い合わせから分離することで、トランザクションコンポーネントのスループットを最大化します。とはいえ、ここには明確なトレードオフがあり、Datomicは無制限の書き込みのスケーラビリティではなく、ACIDトランザクションを選び、このトレードオフが適切に働く領域をターゲットにしています。一貫性はシステムの特性をシンプルにして、強靭なソリューションを生み出します。しっかりとした理由なしに一貫性を破棄するべきではありません(そのような理由がある場合もありますが、自分のケースに当てはまるかどうかを確認する必要があります)。

従来のRDBMSはデータを操作するために強力な論理的、宣言的、集合指向言語を提供します。しかし残念ながら、この強力さはデータベースサーバ側限定であり、データがアプリケーションに渡ってしまうとネストしたforループによってその効果がなくなってしまいます。Datomicは分散インデックスを提供し、宣言的問い合わせコンポーネントをアプリケーションサーバ層に配置できるようにします。この問い合わせエンジンはDatomicがホストするデータとインメモリのデータソースの両方のデータを一貫性のある高レベルの手法で操作できます。

全般的な関心

Datomicの設計には多くのコンセプトが取り込まれています。

  • 単純さと合成。システムはひとつのことを行うサービスを複数組み合わせて構成するべきであり、サービスは互いを知っているべきでない。ストレージやキャッシュのような領域には良く考えられたシンプルなコンポーネントがすでにあり、統合可能である。

  • ストレージと問い合わせのスケーラビリティと弾力性。事前の構成なしで動的にマシンを追加したり削除したりすることでストレージや問い合わせの能力を大きくしたり小さくしたりできるべき。

  • 配置場所の柔軟性。あるコンポーネントは別のコンポーネントのある場所を気にしない。

  • 全般的な不変性。プログラミングで更新をするというのは時間が経過したということを表す。ほとんどのプログラミングは不変値を使って行われるべき。Datomicではデータベース自体がひとつの値になっている。

  • インターフェイスとしてのデータ。システムはプログラミング可能であるべき。そのためには主要なインターフェイスはデータ駆動であるべきで、複雑な構文であってはならない。Datomicではスキーマ、トランザクション、問い合わせ、問い合わせ結果すべてが、リストやマップのような普通のデータ構造で定義されている。

論理モデル

Datomicは次のサービスで成り立っています。
 

  • ストレージ
  • トランザクションのコーディネーションと通知
  • インデキシング
  • アプリケーションデータモデルと問い合わせ
  • キャッシング

ストレージに必要なサイズはわずかです。第1のストレージは小さな(< 64k)BLOBです。ストレージの使われ方は従来のデータベースがファイルシステムと同じで、ログとインデックスセグメントの領域として使われます。これらのセグメントは不変です。ログやインデックスのルートを参照するためにいくつかのキーが使われます。これらのキーを使うことでのみストレージを変更できます。変更するためにはストレージ側が書き込み/読み取りの一貫性と条件付きあるいはバージョン付きのプットを提供する必要があります。

情報の追加はトランザクションコーディネータにノベルティを発行するという形で行われます。コーディネータはトランザクションをシリアライズして、ACID特性を保証し、新しい情報をストレージ内のログセグメントへ書き込みます。永続化ストレージに対しては、コーディネータがトランザクションサブミッタと他の接続に対して、トランザクションの結果の新しい情報を通知します。

ストレージの第2の使い方はインデックスです。インデックスの実体はデータベースのデータです。さまざまな順でソートされており、セグメントのツリーを表します。インデキシングサービスは定期的にストレージのログから新しいデータを取得してインデックスに組み入れます。インデックスセグメントは不変なので、インデキシングの処理では常に新しいインデックスツリーが作成されます。

アプリケーションサーバ層から見るとDatomicはメモリ内の値のように見えます。データベースはエンティティとその属性が形成するグラフのように見えます。加えて、データベースオブジェクトはインデックスに対する反復的なアクセスを提供します。そして、データベースは宣言的問い合わせの引数としても働きます。データベースの'現在'の状態を表示するには、データベースオブジェクトは最新のインデックスと永続化されたインデックスが最後に生成されてから発生したノベルティのインメモリのインデックスを合わせる必要があります。

また、Datomicはアプリケーションサーバに組み込みの問い合わせエンジンを提供します。このエンジンはデータベースの値と同様にメモリ上のコレクションも処理できます。

Datomicのモデルにはキャッシュが完全に統合されています。アプリケーションレベルで問い合わせの結果をキャッシュしてサーバの負荷を軽減するという普通のキャッシュの使い方とは違い、Datomic自体がキャッシュを管理してインデックスセグメントをキャッシュして、インデックスセグメントをストレージからメモリやアプリケーションのプロセスに展開します。インデックスセグメントが不変で、問い合わせが分散されているので、このような問い合わせの'下'のキャッシュが実現できます。

物理モデル

論理モデルをそのまま物理モデルに展開できます。ほとんどのサービスが複数の独立したサブシステムで動きます。

 

  • ストレージサービス

驚くかもしれませんが、Datomicはディスクは関係ありません。上述した最小限の要求を満たす、さまざまなストレージサーバとシステムに統合できます。例えば、

  • インプロセスのメモリ(ストレージではない)。Datomicは完全にメモリ内で動かすことができます。これは開発やテストで便利です。
  • SQL。JDBCが使えるSQLデータベースであればストレージとして利用できます。
  • キー/バリューストア。DynamoDBのような次世代分散キーバ/リューストアはDatomicに向いています。
  • メモリグリッド。冗長メモリが十分丈夫であればInfinispanのような分散データグリッドで利用できます。

このようにストレージを'サービス化'したことで多大な柔軟性を手に入れました。多くの場合、Datomicは専用のストレージリソースを必要としません。テーブルをひとつ追加するだけでDatomicに従来のデータベースを使わせることができます。DynamoDBのようなスケーラビリティの高いストレージを使う場合、Datomicも同様の弾力的な読み取りスケーラビリティを獲得します。これはコンポーネントベースの設計の利点のひとつです。読み取りと書き込みのスケーリングが別のトレードオフになるのです。

Datomicはストレージの違いをカプセル化して、異なるストレージでも全く同じように処理します。あるストレージから別のストレージへ単純なエクスポート/インポートでシステムを移行できます。アプリケーションのストレージ変更もプロパティファイルとURIの変更だけで済みます。

  • トランザクタ

トランザクタはトランザクションのコーディネーション専用のプロセスです。アプリケーションサーバのピアから接続を受け付けます。これらの接続からトランザクションを受け付け、シリアライズして、ストレージにログセグメントをコミットし、接続しているすべてのピアに新情報をブロードキャストします。現時点では、インデキシングもトランザクタ上のバックエンドプロセスとして動作しています。スタンバイとして第2のトランザクタを走らせておくことでトランザクタの可用性を高くできます。ストレージは共有されているので、アクティブなトランザクタとスタンバイの間に専用のコネクションは必要がありません。トランザクタには専用のストレージはありません。読み取りや問い合わせの読み込みもしません。このように、一枚岩の設計と比べてコネクションの数が少なくて済みます。しかし、Datomicは無制限の書き込みのスケーラビリティが必要な場合には向いていません。

  • ピアライブラリ

データベースの値を表すコードや接続のコード、メモリインデックスや問い合わせエンジンは'ピア'と呼ばれるJVMのライブラリで提供されます。このライブラリが動作するアプリケーションサーバがデータベースサーバと同等の機能を持つようになることのでピアと名付けました。このライブラリはJava、Clojure、Scala、JRuby、GroovyなどJVM言語で利用できるJava APIを持ちます。ピアは直接(読み取り専用で)ストレージにアクセスします。また、インデックスセグメントのキャッシュを持ちます。このキャッシュの中でインデックスセグメントはJVMオブジェクトに展開されています。

このピアのレベルでプログラミングするのは、クライアント-サーバ型のデータベースでプログラミングするのとは別種のように感じるでしょう。ピアは完全な複製ではないものの、高速にデータをキャッシュするので、データベースがメモリ内のオブジェクトのように感じられます。ORMのように下層を隠蔽しているのではありません。問い合わせはローカルで実行されます。データベースで問い合わせが実行されるというよりは、データベースが問い合わせの引数になります。問い合わせはひとつのデータベースやデータベースと普通のコレクションの組み合わせを扱えます。

DatomicにはDatalogクエリエンジンがあります。Datalogは学習が簡単で、パターン指向の問い合わせ言語でDatomicのデータモデルに適した言語です。SQLのように集合指向で関係を記述できます。また、問い合わせエンジンの世界とは別次元のように感じるかもしれませんが、他の問い合わせ言語を使ってインデックスにアクセスすることもできます。例えば、ClojureのユーザはClojureのPrologのようなcore.logicライブラリを使ってDatomicに問い合わせできます。

アプリケーションのすべての通信はデータ駆動APIを通じて行われます。

  • memcache

Datomicはインプロセスのピアキャッシュとストレージの間の第2層のキャッシュとしてmemcacheクラスタを利用できます。上述した通り、これは問い合わせの'下'のインデックスセグメントのキャッシュです。インデックスセグメントは不変で、特定の問い合わせ結果ではなく、問い合わせ結果のソースなので、このキャッシュはとても便利です。キャッシュの一貫性や有効性のような一般的なキャッシュの複雑さがないからです。ストレージに書き込んだときにmemcacheにデータをキャッシュするようにトランザクタを設定しておけば、初めての読み取りでもキャッシュにヒットします。これによって、ストレージスケーラビリティと性能が格段に改善します。ストレージと同じようにDatomicには専用のmemcacheクラスタは必要ありません。UUIDベースのキーを使うので他のキャッシュと衝突することはありません。

REST APIとクライアント

DatomicにはRESTコンポーネントが付いており、これを使うとピアライブラリで動いているプロセスをDatomic APIをサポートしたHTTPサービスに変換できます。JVMで動作しない言語やピアライブラリに完全なインプロセスの機能が必要ない軽量クライアントはこのDatomic APIを利用できるでしょう。このRESTサービスはtext/htmlメディアタイプを経由して確認可能で自己記述的です、アプリケーションはapplication/ednメディアタイプをリクエストします。このメディアタイプはednフォーマットによるデータの伝送をサポートします。

REST APIのクライアントはデータベースのキャッシュがプロセス内にある場合の利点をほとんど失いません。Datomicのモデルの特性も維持します。データのプログラミング、データソースをまたいだ問い合わせやプログラムデータへの問い合わせの組み込みなどの特性です。独立した問い合わせがトランザクションなしで同じように動作します。データベースの値がパーマリンクを持っているからです。

REST APIのクライアントはピアと同型のAPIを呼び出して、ピアのAPIを呼び出した場合と同じデータ構造を受け取り、同じデータ構造を渡します。この記事ではREST APIについてピアのAPIほど詳しく説明しません。データをプログラミングするという方法は優れたアイディアです。

要約

この記事でDatomicの設計方針といくつかの細部について触れていただければ幸いです。とにかく、この製品のアーキテクチャは不変性の設計上の価値についてたくさんの例を提供しているはずです。一枚岩のアーキテクチャから離れつつ、その機能性を保持しようとすれば、Datomicのようなサービスの合成物としてのデータベースはより一般的になるでしょう。

Datomicには他にもさまざまな特徴があります。情報モデルや、プロセスの具象化、バリューとしてのデータベース、問い合わせモデル、時間モデルなどです。詳細はDatomicのドキュメントで学習できます。

著者について

Rich Hickey氏はプログラミング言語Clojureの作者でDatomicの設計者。25年以上ソフトウエア開発者として働き、スケジューリングシステム、ブロードキャストオートメーション、オーディオ分析、指紋採取、データベース設計、イールドマネイジメント、投票場出口調査システム、マシンリスニングなどさまざまな分野でさまざまな言語を使った経験を持つ。

この記事に星をつける

おすすめ度
スタイル

こんにちは

コメントするには InfoQアカウントの登録 または が必要です。InfoQ に登録するとさまざまなことができます。

アカウント登録をしてInfoQをお楽しみください。

あなたの意見をお聞かせください。

HTML: a,b,br,blockquote,i,li,pre,u,ul,p

このスレッドのメッセージについてEmailでリプライする
コミュニティコメント

HTML: a,b,br,blockquote,i,li,pre,u,ul,p

このスレッドのメッセージについてEmailでリプライする

HTML: a,b,br,blockquote,i,li,pre,u,ul,p

このスレッドのメッセージについてEmailでリプライする

ディスカッション

InfoQにログインし新機能を利用する


パスワードを忘れた方はこちらへ

Follow

お気に入りのトピックや著者をフォローする

業界やサイト内で一番重要な見出しを閲覧する

Like

より多いシグナル、より少ないノイズ

お気に入りのトピックと著者を選択して自分のフィードを作る

Notifications

最新情報をすぐ手に入れるようにしよう

通知設定をして、お気に入りコンテンツを見逃さないようにしよう!

BT