は良い情報源だけど、初めてこのドキュメントを読むときにはちょっと大変かも。新しい用語がいっぱいで、任意の用語を理解するための説明に、まだ知らない用語が含まれていたりしてドキュメントを追うのも一苦労。というわけで、このままだと新しい利用者に対して敷居が高いので、簡単なリファレンスを提供しようという次第であります。これは単なる用語集なので初めから終わりまで読む必要はないです。いくつかのセクションで関連する内容は重複して説明されてます。
- Anti-Entropy
Anti- entropyとreplica synchronizationは異なるノード間で最新のデータを共有、保持するためのメカニズムです。次のように動作します。メジャーコンパクション (compactionを参照)実行中のサーバは、近隣のサーバとMerkleTreeを交換するためにTree状のデータをやりとりします。MerkleTreeはColumnFamilyのhash値です。このMarkelTreeが一致しない場合、 ノード間のデータに不整合がある事になるので、最新のデータはどれなのか?を決定して、最新のものは現状維持、古いものはリペアする必要があります。このTreeを比較、検証する責任はorg.apache.cassandra.service.AntiEntropyService クラスにあります。AntiEntropyServiceはシングルトンパターンで実装されています。またstatic なDifferencerクラスも定義されており、ここでは二つのMerkleTreeを比較して相違があれば、その部分の不整合解消に着手します。
Anti- entropyはAmazonのDynamoで使われており、Cassandraで はそれを模しています。
Dynamoでは Anti-entropyの実装にはMerkleTreeが使われており、Cassandraも同様です。ただちょっと実装が違います。 CassandraではColumnFamily毎にMerkleTreeを保持しており、メジャーコンパクション中にスナップショットとして作成され、 同一リング上の近隣ノードとやりとりする瞬間だけ保持します。こうすることでディスクI/Oを削減することができます。(訳者脚注:代償としてコンパクションの時間が長くなるため、更新停止時間は長くなる可能性はありそう)どのように不整合の解消を行うか、より詳細な情報はReadRepairを参照してください。
- Async Write
ドキュメント等で出てくる"async writes"は単純に非同期書き込みを意味しています。Cassandraではバッファに書き込む時にExecutorServiceやFuture<T>のようなjava.util.concurrent library componentsを使いまくっています。
- Avro
Thriftの代わりになるCassandraのRPCクライアントです。AvroはHadoopのサブプロジェクトでDoug Cuttingによって作成されました。機能的にはThriftと同等ですが、動的なデータ構造をシリアライズできる点でThriftより優れています。また静的なコード生成も必要ありません。また、ThriftからAvroに移行したもう一つの理由として、ThriftはFacebookよりASFに寄与されましたが、それ以降、開発活動があまり活発ではないためです。このためCassandraサーバプログラムのorg.apache.cassandra.thrift.CassandraServerは、org.apache.cassandra.avro.CassandraServerにポートされるでしょう。執筆時(訳者脚注:2010/5/14かな?)では未完成。より詳細な情報はAvroのプロジェクトページで確認できるでしょう。 http://avro.apache.org
- Bigtable
Cassandra の前には、2006年にGoogleによってGFS上で動作する高速なカラム型データベースであるBigtableが作られました。Cassandraは sparse array dataや、ディスクを利用するSSTableというデータファイルフォーマットの仕様をBigtableから受け継いでいます。Yahoo!の HBaseはBigtableのクローンです。完全なBigtableの仕様はhttp://labs.google.com/papers/bigtable.htmlで読むことができます。
- Bloom Filter
(訳者脚注:wikipediaの説明がわかりやすいです。http://ja.wikipedia.org/wiki/%E3%83%96%E3%83%AB%E3%83%BC%E3%83%A0%E3%83%95%E3%82%A3%E3%83%AB%E3%82%BF)
簡単に言うと、BloomFilterとは集合に要素が存在するかテストするための不確定なアルゴリズムです。不確定なので偽陽性(誤検出)の可能性はありますが、偽陰性はありません。Bloom Filterはデータ集合の値をbit配列に格納し且つ、大きなデータ集合を要約したものに圧縮します。この要約したものは定義上、オリジナルデータをそのまま扱うより空間効率が高いです。Cassandraはキーのルックアップ時にかかる高コストのディスクI/Oを削減するためにBloomFilter を使います。全てのSSTable毎にBloomFilterが存在します。クエリーが実行された際に、ディスクアクセスの前にBloomFilterをチェックします。このフィルターが対象要素が集合に存在しない事を示せば、それは確実に存在せずディスクI/Oは不要になり、集合に存在する可能性がある場合のみ、ディスクI/Oするよ。BloomFilterにとって偽陽性の可能性がある事はデメリットですが、それ以上にとても早く動作するのがメリットです。なぜなら配列や、ハッシュ構造や、リンクリストとは違い要素を完全な状態で保持しないため、空間効率がとても良いのです。そのかわり大量のメモリを利用し、ディスクI/Oを削減します。アルゴリズムの特性上、結果として要素が増える毎に、偽陽性も増加します。BloomFilterはHadoop、 Bigtable、Squidで使われています。BloomFilterは創案者のBurton Bloomにちなんで名づけられました。
- Cassandra
ギリシャ神話では CassandraはトロイのKing PriamとQueen Hecubaの娘です。彼女はとても美しかったのでアポロは彼女に千里眼を与えました。しかしアポロからの恋のアプローチを拒んだ際に、能力に頼らず未来を言い当てるように罰を受けてしまいました。そんな彼女を誰も信じようとはしませんでした。彼女はCassandraはトロイの破壊を予見しましたが、それを止めるには力不足でした。Cassandraデータベースは、そんな彼女にちなんで名づけられたようです。
このデータベースはapache projectとしてhttp://cassandra.apache.orgで稼動中です。Cassandraは以下に示すような特性を持っています。中央集権型ではない、伸縮自在、耐障害性、一貫性レベルをチューニング可能、高可用性、データセンタをまたいだコモディティサーバ群で超スケール可能な設計などなど。Digg, Facebook, Twitter, Cloudkick, Cisco, IBM, Reddit, Rackspace, SimpleGeo, Ooyala, and OpenXのような企業で使われています。CassandraはFacebookのサーチ性能の問題を解決するために作られました。チームは Facebookのサーチ担当エンジニアPrashant Malikと、Jeff Hammerbacher, Avinash Lakshman, Karthik Ranganathanによって率いられました。このコードは2008/7にGoogleCodeにOSSとしてリリースされました。2009/3には ApacheのIncubatorProjectに移動し、2010/2/17にはトップレベルプロジェクトに格上げされました。"A Decentralized Structured Storage System"と呼ばれるFacebookのLakshmanとMalikによるCassandraの論文はここにあります。http://www.cs.cornell.edu/projects/ladis2009/papers/lakshman-ladis2009.pdf Avinash Lakshmanによる2008のブログ投稿では、FacebookでのCassandraの使用法について述べています。 http://www.facebook.com/note.php?note_id=24413138919&id=9445547199&index=9 Cassandraが何故適切に名づけられたのか(順調に成長を遂げているのか?)を理解するのは簡単です。コミュニティはCassandraや他の同様のNoSQLの時代がくると言い切っています。Amazon, Google, FacebookやTwitterといった企業が結果整合性のデータベースを広範囲で利用しているのにも関わらず、たくさんのアンチはいるみたいです。 GoogleのRanTavoryによって書かれたJavaクライアントHectorはCassandraの兄弟にちなんで名づけられました。
- Chiton
古代ギリシャでChitonは布の衣服を意味し、一般的には袖なしで男女問わず着衣していました。ChitonはBrandon Williamsによるオープンソースプロジェクトと同名で、このプロジェクトはPythonGTKで作成されたCassandra向けのブラウザソフトウェアです。現在は http://github.com/driftx/chitonでホストされています。関連するプロジェクトとしてTelephusがあります。これはTwisted Pythonで書かれたCassandra向けの低レベルなAPIクライアントです。現在はhttp://github.com/driftx/Telephusでホストされています。
- Cluster
Clusterとは2つ以上のCassandraインスタンスが協調して動作している状態です。これらのインスタンスはGosshipプロトコルを利用して他のインスタンスと通信します。Clusterに新たにインスタンスを追加する場合には次に示す手順が必要です。最初にSeedNode を設定します。次にCassandraがlistenするGosshipと、Thrift用のポートを指定します。Clusterの設定ができたら、正しくセットアップできたかNodeToolで検査しましょう。
- Column
ColumnはCassandraのデータモデルでもっとも基本的な単位を表します。Columnは3つの要素で構成されます。 name(時々「key」として参照されます)と、valueと、timestampです。Columnのvalueはtimestampとともに、クライアントによって提供されます。nameとvalueのデータ型はJavaのバイト配列で通常はStringとして表されます。timestampのデータ型はプリミティブなlong型です。Column群はマルチスレッドの諸問題を避けるため不変です。Colum群はColumnFamiliesに所属します。ColumnFamilyはそれぞれ別のファイルに格納されるので、関連のあるColumnは同じColumnFamilyに所属するように定義してください。Columnはorg.apache.cassandra.db.IColumnでインターフェースとして定義されています。このインタフェースでは、Columnからvalueをバイト配列として取得するメソッドや、SubColumnsをCollection<IColumn>で取得するもの、最新の変更を検索するものなどが提供されます。Column群は次に示すいずれかのタイプに分類されます。AsciiType, BytesType, LexicalUUIDType, LongType, TimeUUIDType, UTF8Type。 ColumnFamilyも参照してください。
- Column Family
ColumnFamilyは簡単に言うとリレーショナルDBのテーブルと同質です。 Column群の順序付けされた集合を格納するコンテナの役割を担います。ColumnFamilyはそれぞれ別のファイルに格納されるので、一緒にアクセスされる可能性があるColumnは同じColumnFamilyに所属するように定義してください。ColumnFamilyはstorage-conf.xmlで定義できます。この定義ファイルでは、RowCacheサイズや、 KeyCacheサイズ、ReadRepairChanceなども設定可能です。 ColumnFamily群は、StandardかSuperいずれかのタイプになりえます。row中のColumnの順序は定義可能です。 Column、KeySpace、SuperColumnも参照してください。
- Column Name
name/valueペアのname部でRowに格納されます。
- Column Value
name/valueペアのvalue部でRowに格納されます。ColumnValue のサイズはマシンのメモリ容量に制限されます。
- Commit Log
CommitLog はCassandraの全ての書き込み操作に対して責任があります。書き込み時実行時に、まず最初にCommitLogが書き込まれるので、障害が発生してもデータは失われないでしょう。それからvalueはパフォーマンスを考慮してmemtable(メモリ上のデータ領域)に格納されます。 memtableが一杯になると格納されていたデータはSSTableに書き込まれます。これはorg.apache.cassandra.db.commitlog.CommitLog で実装されています。全ての書き込み、削除操作毎にRowMutationオブジェクト形式のエントリがシリアライズされてCommitLogに追加されます。これらのオブジェクトはCommitLog領域に配置されます。 CommitLogは128Mに到達すると新しいCommitLogが生成され、以降は新しいCommitLogに書き込みが行われます。
Cassandraクラスタが高い信頼性を提供するためにはサーバ設定ファイルを検査する必要があります。デフォルトでは、CommitLogSyncは「periodic」に設定されています。これは定期的にしかディスクにsyncしない事を意味します。つまりこの設定時はwrite-behindキャッシュ(訳者脚注:OSのページキャッシュ上に存在する状態)上のデータがディスクに同期されず失われる可能性があるという事です。この設定を「periodic」から「batch」に変更することで、writeが完了する前にCommitLogをディスクに同期するようになります。この変更によりパフォーマンスに影響がでますが、これは必要なトレードオフです。 またCommitLogSyncに設定した場合は、CommitLogSyncBatchWindowInMSにも適当な値を設定する必要があります。「MS」は、それぞれのsync操作の間隔をミリ秒単位で表したものです。なおこの設定はレプリケーションを利用する複数ノードクラスタ環境では一般的には必要とされません。なぜならレプリケーションの「定義」によっては、書き込みが他のノードに対して成功するまで完了を認めない設定もあるからです。
もし「batch」を設定する事に決めた場合は、writeがディスクに同期するまでブロックされるので、パフォーマンスを考慮してCommitLogを別のデバイスに配置するとよいでしょう。
- Compaction
Compactionは蓄積された大きなデータファイル群をマージすることで、ディスクスペースを空けるためのプロセスです。これは簡単にいうとリレーショナルDBにおけるテーブルの再構築と同質です。Compactionする事で、マージされたデータはソートされ、新たにインデックスが生成されます。そして新しくマージ、ソート、インデックスされたデータは一つの新しいファイルに書き込まれます。Compaction実行中には次に示す操作も実行されます。keyのマージ、Column群の結合、そしてtombstones(訳者脚注:削除フラグがたったデータ。後述のtombstonesを参照)の削除です。このプロセスはorg.apache.cassandra.db.CompactionManager.CompactionManagerクラスで管理されます。また実行状態を監査できるようにMBeanインタフェースを実装しています。Cassandraでは異なるタイプのCompactionが存在します。メジャーCompactionは次の二つのうちの一つをトリガーにして実行されます。ノードの探査中か、自動的に行われます(訳者脚注:データサイズが一定の基準値を超えた場合とか)ノード探査はTreeRequestメッセージを近隣のノードに送ります。これを受け取ったノードはColumnFamilyの妥当性をチェックするために、すぐさまread-onlyなCompactionを実行します。read-onlyなCompactionは次のステップで行われます。
1. ColumnFamilyから割り当てられたkeyを取得します
2. 一度Row群が妥当性チェックされます。この結果ColumnFamilyが妥当性チェックする必要があるなら、MerkelTreeが生成され、近隣のノード群にブロードキャストされる事になります。
3. MerkleTreesはDifferencers(妥当性のチェックと、差分比較に必要なtree群)のリストとしてお互いに持ち運ばれます。
4. 比較はStageManagerクラスによって実行され、ジョブを実行する際の並列実行の取り扱いに関して責任を持ちます。この場合StageManagerは、Anti-EntropyStageを利用します。これはorg.apache.cassandra.concurrent.JMXEnabledThreadPoolExecutorクラスを利用し、シングルスレッドでCompactionを実行します。そして監査のためにMBean操作を可能にします。
- Compression
データの圧縮は将来的にはサポート予定ですがバージョン0.6では未サポートです。
- Consistency
Consistencyはデータベースにトランザクションが半端な状態を残さない事を意味します(整合性が必ず強制される)。これはリレーショナルDBで考案されたもので、ACID特性の一つでもあります。Cassandraでは次のようにConsistencyの度合いを計算できます。
N = レプリカが格納されるノードの数
W = 書き込み成功を応答する前に、書き込みが受領されなければならないレプリカの数
R = 読み込み操作の際に、コンタクトする必要があるレプリカの数
W + R > N = strong consistency
W + R <= N = eventual consistency
- Consistency Level
ここでは書き込み操作時に複製される必要があるレプリカの数や、読み込み操作時に成功か否か判定するために、読み込みに応答する必要があるレプリカの数を設定可能です。ConsistencyLevelはReplicationFactorによって設定します。実際のcluster内のノードの数ではありません。パフォーマンスを制御可能なように複数のConsistencyLevelがあります。もっともパフォーマンスを高くするにはConsistencyLevelを一番低くすることです。書き込みと、読み込みはそれぞれ別に設定します。
・書き込み操作向けの設定値
ZERO: 書き込みはバックグラウンドで非同期に制御されます。これは一番速い方法ですが、信頼性も最も低いです。
ANY: バージョン0.6で提供された設定。一つのノードに対して書き込みが成功したらOK。しかもhint(訳者脚注:駄目だった場合に他の生きてるノードに更新内容をキューイングする手続き。詳細はHinted Handoffを参照。)のみがOKだった場合も含みます。これは比較的低いConsistencyLevelです。
ONE: 一つのノードに対して書き込みが成功したらOK。これは対象ノードのCommitlogとmemtableへの反映が完了した事を意味します。一つのノードから返答があったら操作は成功とみなします。
QUORAM: quoramは操作が成功するために合意を得る必要があるノードの数を示します。これは「<ReplicationFactor> / 2 + 1」で決定されます。なので例えば10のReplicationFactorを指定していたら6レプリカ複製される事が、操作が成功するために必要なquoramになります。
DCQUORAM: quoramの取得先ノードを同一データセンターに限定したバージョンです。これにより高いレベルのConsistencyLevelと低レイテンシのバランスが期待できます。
ALL: 全部成功しなきゃだめ。一つでも失敗したらアウト。最も高いConsistencyLevelでかつ最も低いパフォーマンス。
・読み込み操作向けの設定値
ONE: 一番最初に返答してきたノードの値を返します。バックグラウンドでread repairを実行します。
QUORAM: 全部のノードにクエリを投げて・・・
ALL: 全部のノードにクエリを投げて最も新しいtimestampを持った値を返します。全ノードの応答を待つので、一つでも駄目なら読み込みは失敗します。
※ZEROという設定値がないことに気がつかれた方もいらっしゃると思いますが、これは意味がありません!
- Data Center Shard Strategy
Replication Strategyを参照
- Decentralized
Cassandraにはマスターサーバは存在せず分散型として設計されています。変わりにボトルネックとSPOFを避けるためにP2Pなアプローチを取っています。分散はCassandraでは重要な概念です。これによりclusterのスケールアップ(サーバの追加)、スケールダウン(サーバの離脱)を最小限のリスクで実現できます。これを実現するためにCassandraで採用している方法はGossipプロトコルを利用することです。
- Denormalization
RDBMSでは非正規化や、冗長なデータを保持する方式は、OLAPのような参照が多いアプリのパフォーマンスを向上させるためにしばしば適用されています。Cassandraでは一般的に非正規化されています。これはパフォーマンス向上のためや、必要とする問い合わせ毎にデータが構造化されるためです。標準的なRDBMSとの違いは、データが一般的に個別のオブジェクト(訳者脚注:問い合わせ毎の結果セットの事かな?)毎に構造化される事です。
- Durability
データベースが信頼できるということは即ち、サーバがクラッシュしたり、突然の電源障害時でも、書き込み完了した操作が保障される事です。Cassandraでは更新内容をCommitLogの末尾に書き込み、サーバがデータファイルから位置を特定するのを防ぐことで高い信頼性を達成しています。CommitLogはファイルシステムに同期される必要があるだけです。同期は定期的か、指定された範囲で一括処理されるか、いずれかの方式で発生します。シングル構成で稼動している時は、ファイルのコアな状態がすぐにはストレージ装置に同期されません。これは書き込みが実行された後にサーバがシャットダウンした場合に、その後のリスタート時に書き込み内容が失われる可能性があるという事です。本番環境ではシングル構成は推奨されないことに注意してください。CommitLogも参照してください。
- Dynamo
DynamoはGoogleのBigtableの仕様をもとにAmazonによって2006に参照実装されたものです。Cassandraの主要な基盤はDynamoをもとにしています。Cassandraは次に示す仕様を踏襲しています。KVS、対称なP2Pアーキテクチャ、gossipプロトコル、結果整合性と操作(読み込み、書き込み)毎のConsistencyLevelの設定。Dynamoの完全な論文はhttp://www.allthingsdistributed.com/2007/10/amazons_dynamo.htmlで読むことができます。
- Elastic
read/writeのスループットともにマシンを追加する毎にリニアに増加します。
- Eventual Consistency
Consistencyとは任意の操作のもとで対象データの内部的な一貫性について述べた特性です。強い一貫性を求められるデータベースの場合には、あるクライアントが書込み操作を実行したら、全ての読み込み処理がすぐに最新の更新された値を返さなければなりません。EventualConsistencyでは大抵すぐには一貫性は保障されませんが、結果的には整合性は取れます("eventually"は転送データ量や、clusterを構成するノード数、これらのノードの地理的な配置状況に依存しますが、通常は全てのレプリカに数ミリ秒で最新のデータが行き渡ります。DNSはEventualConsistencyアーキテクチャを利用したポピュラーな例です。
EventualConsistencyは時々"weak consistency"と呼ばれます。EventualConsistencyはここ数年で一般的になってきました。巨大なスケーラビリティをサポートできるからです。トラディショナルな完全な一貫性をもったDBで高いスケーラビリティを維持するには、管理のオーバーヘッドが負荷になってきます。もちろんEventualConsistencyにもデメリットはあります。複雑なプログラミングモデルを実装するケース等です。けれどもCassandraにおけるEventualConsistencyの設計はDynamoの使用法に基づいています。CassandraはConsistencyLevelを設定可能な点でより良い特性をもっています。これはCassandraではConsistencyLevelの設定次第で、完全な一貫性も確保できることを意味します。
Riak, Voldemort, MongoDB, Yahoo!'s HBase, CouchDB, Microsoft's Dynomite, and Amazon's SimpleDB/Dynamoは他の結果整合性データストア製品群です。
- Failure Detection
Failuredetectionは耐障害性をもった分散システム上で障害が発生したノードを検知するプロセスです。Cassandraの実装はAccrualFailureDetectionのアイディアに基づいています。この論文は2004のJapan Institute of Science and Technologyで初めて発表されました。AccrualFailureDetectionは2つの主要なアイディアに基づいています。障害検知は監視対象アプリとは独立して柔軟であるべきという点と、障害検知モニタの障害発生判断をどのように信頼して、継続的に障害の嫌疑レベルを出力していくこと、以上の2点です。これはネットワーク環境の変動を考慮に入れることができるので望ましいです。heartbeatのサンプリングに基づく障害嫌疑の予兆は流動的で活発なので、単純な成功か失敗による判断はよろしくないです。Cassandraでの障害検知の実装はorg.apache.cassandra.gms.FailureDetectorクラスです。AccrualFailureDetectionの論文はhttp://ddg.jaist.ac.jp/pub/HDY+04.pdfで読むことができます。
- Fault-Tolerant
Faulttoleranceとはシステムの一つ以上のコンポーネントに障害が発生した場合でも、そのシステムが提供するオペレーションを全面的に継続して稼動することができるシステム仕様の事です。Faulttoleranceはシステムが一部劣化する場合にも用いられる事があります。例えば、なんらかの障害によってそのシステムに劣化が発生した際に、その劣化したパフォーマンスの影響範囲が故障したコンポーネントだけに限定される場合などです。
- Gossip
gossiperはcluster内の全ノードが、自分以外のノードの重要な状態情報に気がつけるようにする責任があります。gossiperは障害中のノードや、まだclusterに参加していないノードに対しても毎秒稼動することでノードの状態を受信できる事を保障します。これは急激に増加する負荷に対しても耐えうるように設計されました。gossipプロトコルはノードをまたいだkeyの再配置をサポートし、障害検知もサポートします。gossipはAnti-Entropy戦略において重要な役割を担っています。gossiperが共有している状態の情報はkey/valueペアで管理されています。Cassandraでは、gossipプロトコルは他のノードに対して常にノード状態の情報を流し続けます。サーバノードがスタートした際には自身でgossiperの輪に入ります。これ以上の情報はorg.apache.cassandra.service.StorageServiceクラスをチェックしてください。gossipに関するamazonの論文も参照してみてください。http://www.cs.cornell.edu/home/rvr/papers/flowgossip.pdf
- Hector
GoogleのRanTavoryによって作成されたOSSプロジェクトでgitでホストされています。HectorはCassandraのJavaクライアントです。これはThriftをラップし、JMX、コネクションプール、F.Oを提供します。
- Hinted Handoff
これは可用性、耐障害性、致命的ではない劣化を確保するためのメカニズムです。書き込みが発生した際に書き込み対象ノードが落ちていた場合に、書き込み内容("hint")を落ちたノードが復活した時にリプレイするために、これを他の生存ノードに格納("handed off")します。これにより次の二つが実現されます。障害ノード復活時に一度ミスっただけでも全てのデータを取得する必要がなくなり、F.Bの時間を削減できます。また低いConsistencyLevelで書き込み性能の向上します。HintedHandoffは、ConsistencyLevelがONE, QUORUM, ALLの時には書き込み成功としてはカウントされません。ANYの時だけカウントされます。しかしながらHintedによる書き込みで格納されたデータは、ANY以外のConsistencyLevelでは読み込むことができません。hintを受け取ったノードは障害ノードが復帰した事をGosshipですぐに検知できます。もし何らかの理由でHintedHandoffが動作しなかった場合は、システムはreadrepairを実行します。
- Key
RowKeyを参照してください
- Keyspace
KeyspaceはColumnFamily群のコンテナです。これはリレーショナルDBにおけるデータベースと同質のものです。Cassandraではアプリケーション毎に分割するするために使います。リレーショナルDBはテーブルの集合ですが、Keyspaceは順序付けされたColumnFamilyの集合です。Cassandraの定義ファイル(storage-conf.xml)でアプリケーションのKeyspaceを定義できます。Keyspaceを定義した場合は、そのReplicationFactorと、レプリカの配置戦略(ラック別とか、DC別とか)も定義できます。Cassandraクラスタでは一つ以上のKeyspaceを持つことができます。(定義したアプリケーション毎には一つまで)ColumnFamilyも参照してください。
- Lexicographic Ordering
Lexicographicorderingとは2つの順序付けされた集合のデカルト積をアルファベット順でソートすることです。
- Memtable
メモリ中のデータ構造で最新のデータが書き込まれています。memtableが一杯になるとディスク上のSSTableに同期されます。
- Merkle Tree
HashTreeという名前なら聞いたことがあるんじゃないかな。MerkelTreeは巨大なデータ集合を小さな形式に要約した2分木構造です。HashTreeでは枝葉は要約(訳者脚注:大抵はhash値です)されたデータブロック(一般的にはファイルシステム中のファイル)のことです。Tree中の全ての親ノードは直接の子ノードのHash値です。きっちりとしたコンパクトな要約ですよね。CassandraではMerkleTreeはorg.apache.cassandra.utils.MerkleTreeで実装されています。CassandraではP2Pのノード間で不変で堅牢なデータのやりとりを確保するために利用しています。MerkleTreeは暗号化や、ファイルや伝送データのベリファイに使われます。GoogleWaveでも使われているようです。創案者のRalph Merkleにちなんで名づけられました。
- Multiget
keyの集合を渡して問い合わせます
- Multiget Slice
keyの集合を渡してcolum集合の一部を取得するように問い合わせます
- Node
Cassandraのインスタンスです。大抵Cassandraのクラスタは複数のノードを持っています。ノードリングと呼ばれたりします
- Node Tool
これはクラスタ構成が正しく設定されているか検査したり、様々なメンテナンス操作を実行するための実行ファイルです。bin/nodetoolに配置されます。NodeToolで実行可能なコマンドはcleanup, clearsnapshot, compact, cfstats, decommission, drain, flush, info, loadbalance, move, repair, ring, snapshot [snapshotname], removetoken, tpstatsです。例えば「nodetool drain」はCommitLogへのあらゆる書き込みを停止させます。
- NoSQL
NoSQLはSQLを利用しない、もしくはリレーショナルデータモデルではないデータベースの総称です。またNoSQLの支持者が、リレーショナルDBは悪い選択なので提案しないけど、他にも選択肢があることを示したい場合に「Not Only SQL」という意味をこめて利用される場合があります。
- Order-Preserving Partitioner
これは次の仕様を持つPartitionerの一種です。rowsはあなたが指示したソート順序でデータを物理的に整列させたkey順で格納されます。Order-PreservingPartitionerを使用するようにColumnFamilyに設定することで、RangeSliceが可能になります。これはCassandraがどのNodeがどのkeyを持っているのか知っていることを意味します。このPartitionerはRandomPartitionerとは対称的な仕様です。効率的な範囲問い合わせが可能になりますが、keyの分散に偏りがでます。Order-PreservingPartitioner(OPP)はorg.apache.cassandra.dht.OrderPreservingPartitionerクラスで実装されています。CollatingOrder-PreservingPartitioner(COPP)と呼ばれる特別なOPPも存在します。基本的にはOPPと同じように振舞いますが、バイトオーダー順のかわりに、English/US辞書順でソートされます。これはロケールを意識したアプリケーションで有効です。COPPはorg.apache.cassandra.dht.CollatingOrderPreservingPartitionerで実装されています。Tokenも参照してください。
- Partition
一般的にPartitionはネットワーク分断を表します。Partitionはスイッチ、ルータ、NICの故障などで引き起こされます。ABCDEという5台のマシンでclusterが組まれていてAB、CDEでサブネットが分かれている場合を考えてみてください。CDEが所属するスイッチに接続障害が起きた場合、AB、CDEでクラスタが分離されネットワーク分断が発生します。Cassandraは耐障害性を備えたDBです。ネットワーク分断のような障害に対しても堅牢です。ネットワーク分断中でもサービスは継続することが可能で、ネットワーク復旧するとすぐにレプリカでデータをマージします。
- Partitioner
Partitionerはどのようにデータを分散させるかを制御します。keyの集合をみつけるためにCassandraはノードが所有している値の範囲を知っておく必要があります。Order-PreservingPartitionerと、RandomPartitionerという二つのがあります。storage-conf.xmlで「<Partitioner>org.apache.cassandra.dht.RandomPartitioner</Partitioner>」のようにPartitioner要素を記述することで設定できます。partitioningはcolumnではなくrowkeysをもとに分散させるので注意してください。partitionerは一度決定したら、データを削除しない限りは変更不可能です。(SSTableは変更不可能なため)Order-Preserving Partitioner、RandomPartitionerも参照してください。
- Quorum
ある操作に対して応答するノードが過半数であることを意味します。ConsistencyLevelで設定可能です。Quorum読み込みではproxyノード(訳者脚注:Cassandraクライアントが接続したノード)が、過半数のノードから同じ値が帰ってくるのを待ちます。これは読み込み操作を遅くするかわりに、古いデータが返却されないことを保障します。(訳者脚注:最新であるとは限りません)
- Rack Aware Strategy
ReplicationStrategyを参照してください
- Random Partitioner
MD5によるBigIntegerTokenでNodeRingにおけるkeyの配置場所を決定するPartitionerです。これはkeyがclusterに満遍なく配置されますが、範囲問い合わせが遅くなります。これはデフォルトのPartitionerです。Partitioner、RandomPartitionerを参照してください。
- Range Slice
keyの範囲でcolumn群の一部を取得する問い合わせ
- Read Repair
NodeRing全体で一貫性を確保するためのもう一つのメカニズムです。読み込み操作で、応答したノードの返却値が一致しない場合、データが古いノードに対してReadRepairを実行するためのメモを残します(非同期で実行するためにキューするという意だと思われる)。ReadRepairはCassandraが読み込み操作で得た最新のデータをもとに、古いデータを保持しているノードを更新するために、書き込み操作することを意味します。これは、まず全てのデータを取得し、マージを実施し(カラム単位で最新の情報を生成する処理かな?)、マージされたデータを同期すべきノードに書き戻すことで実現されます。データ不整合の検知はタイムスタンプとチェックサムの比較で実施されます。このデータを一致させるまでの一連の流れは、org.apache.cassandra.streamingパッケージに実装されています。
- Replication
一般的な分散システムでは、複数のマシンに、複数のコピーを格納することで、マシンの障害や、ネットワーク分断が発生してもclusterがデータを維持することができます。これを理解するための手助けとしては、キャッシュもReplicationの一つという事です。CassandraではReplicationは高いパフォーマンスと、高可用性、耐障害性を提供するための手段です。
- Replication Factor
CassandraはConsistencyLevelの強度を高めるために、どの程度パフォーマンスを犠牲にするのかを決定するために設定可能なReplicationFactorを提供します。読み込み、書き込みのConsistencyLevelはReplicationFactorに基づいています。これはノードをまたいだレプリカの複製数を示します。ReplicationFactorはstorage-conf.xmlのReplicationFactor要素で設定可能です。
- Replication Strategy
レプリケーション戦略はどのようにレプリカを分散させるかを決定する配置戦略についても言及します。最初のレプリカは常にTokenが所属するkey範囲を担当するノードに配置されます。他のレプリカは設定可能なレプリケーション戦略によって分散されます。レプリケーション戦略をプラガブルにするためにGOFのデザインパターンの一つ「ストラテジパターン」が採用されていますが、Cassandraでは創造的な3つのパターンが提供されます。レプリケーション戦略を選択することは、どのノードがどのkey範囲を担当するのかを決定することであり、どのノードが書き込み対象になるかを決定することでもあります。これは戦略によって性能に大きな影響があるという事です。Cassandraはネットワーク構成や、そのほかの要件に応じて柔軟に対応できるレプリケーション戦略を用意しています。
最も単純な戦略はRackUnawareStrategyと呼ばれています。名前の通りラックの位置を気にしません。
より気の利いたポピュラーな戦略としてRackAwareStrategyがあります。この戦略はCassandraクラスタが一つ以上のDCにまたがって収容される場合には重要です。この戦略は次に示す2つの処理を実施します。最初のレプリカは前述の通りTokenに基づいて自動的に決定されます。2番目のレプリカは最初のノードとは異なるDCに配置されます。3番目以降のレプリカは同一DC内の異なるラックに配置されます。
3番目の戦略はDatacenterShardStrategyです。これはRackAwareStrategyより均等にDC間でデータを配置する指定が可能です。これを使うにはdatacenters.propertiesを用意する必要があります。このファイルにそれぞれのDC毎に要求されるレプリケーション戦略を指定できます。このファイルはorg.apache.cassandra.locator.DataCenterShardStrategyクラスによって読み込まれ、実行されます。レプリケーション戦略群はorg.apache.cassandra.locator.AbstractReplicationStrategyクラスを継承したものです。このクラスを継承することで独自のレプリケーション戦略を実装する事が可能です。
- Row
ColumnFamilyでは、RowはColumnNameに対するColumnValueを結びつけてソートしたデータです。SuperColumnでは、RowはColumnNameに対するColumnValueを結びつけた集合をSuperColumnNameと結びつけてソートしたデータです。RowKeyはRow毎に定義されます。Rowはcolumn群のname/valueペアの集合になります。一つのRowあたりのサイズはディスク領域を超過することはできません。Row群はRandomPartitioner, OrderPreservingPartitioner, CollatingOrderPreservingPartitionerの内のいずれか一つのPartitionerによって配置されるノードが決まります。Rowはorg.apache.cassandra.db.Rowクラスで定義されています。Rowkeyも参照してください。
- Row Key
単純に"Key"とも呼ばれます。RowKeyはリレーショナルモデルにおけるプライマリキーと同質です。これによりRowを特定する事ができます。データ型は任意の長さのStringです。ThriftインタフェースではJavaクライアントはRowkeyをUTF-8エンコードされたものとして扱いますが、他の言語クライアントではそうとは限らないので、場合によってはアプリでUTF-8への変換を行う必要があるかもしれません。
- SEDA (Staged Event Driven Architecture)
Cassandraは並列実行環境で高い性能を得るためにSEDAを採用しています。SEDAはマルチスレッドによるオーバーヘッドを無視できるような性能を出すことを目論んでいます。マルチスレッドのオーバーヘッドには、スレッドのスケジューリング、ロックの競合、キャッシュミス(訳者脚注:L2キャッシュなどCPUアーキレベルでのお話しかな)等があります。SEDAは一つの仕事を同じ一つのスレッドで完結させません。これはより複雑な実装をすることになりますが、よりよいパフォーマンスをもたらします。したがって、Cassandraの主要な処理(Reading, Mutation, Gossiping, memtable flushing, Compaction)は、Stageとして実装されます。Stageは本質的には分割されたイベントキューです。イベントがキューに入った際に、アプリケーションによって実装されたイベントハンドラが発動します。コントローラは要求に応じてそれぞれのStageに適当なスレッド群を動的に割り当てます。SEDAによる利点は高い並列実行性と、CPU、メモリ、DISK、ネットワーク資源の効率的な利用を実現します。SEDAの提唱者(Matt Welsh, David Culler, and Eric Brewer)による論文を見ることができます。http://www.eecs.harvard.edu/~mdw/proj/seda Stageも参照してください。
- Seed Node
SeedNodeはCassandraクラスタにすでに参加しているノードが担当します。これは新しいノードがクラスタに参加する際に利用されます。SeedNodeは新しい参加ノードに対してクラスタの形状や、状態の情報を伝えるためにgossipします。SeedNodeはクラスタで複数存在する可能性があります。storage-conf.xmlで次のように設定します。「<Seeds><Seed>10.0.1.1</Seed></Seeds>」
- Slice
読み込み系問い合わせの一種です。任意の一つ以上のColumnNameを取得する場合は「get_slice()」を使いましょう。複数Keyを渡して複数Column群を取得する場合は「get_range_slice()」を使いましょう。
- Snitch
Snitchはノードとネットワークの物理的な位置を結びつけるためのCassandraの手法です。新ノードの発見と効率的なネットワーク越しのリクエストを実現するために、適切なノード位置を決定するのに役に立ちます。Snitchは何種類かあります。
EndpointSnitchは、例えば、二つのノードが同一DCに属するのか、同一ラックに属するのかを決定します。これは対象ノードのIPアドレスの2、3番目のオクテットに基づいてノード間の相対的な距離を推測することで判断します。
DataCenterEndpointSnitchは、ラックとDCとの紐付け情報と、サブネットに基づいたラックの指定をもとに判断します。
PropertyFileSnitchは「cassandra-rack.properties」というファイルで、IPアドレス単位でラックとDCを紐付けを行い判断します。
Snitchクラス群はorg.apache.cassandra.locatorパッケージにあります。
- Sparse
リレーショナルモデルではテーブル毎に例え値がnullの場合でも、カラム毎に値を保持しなければなりませんが、一方Cassandraでは、スパースもしくはスキーマフリーなデータモデルを提供します。これは定義したColumn分データを持つこともあれば、ほんの一部だけ持つ場合もあるという事です。これは空間効率を考慮しています。例えば、1000×1000のスプレッドシートをリレーショナルDBで実現することを考えてみてください。多くのセルがnullの場合は非効率です。
- SSTable
SSTableは"Sorted String Table"の略です。disk上のデータ格納形式はGoogleのBigtableを継承しています。バッファリングとデータのソートをするために、SSTableへの書き込みの前に、ログ構造のMemtableへの追記書き込みのみを行います。このためSSTableは書き込みで高いパフォーマンスを発揮します。またコンパクションも可能です。Compactionを参照してください。SSTableは不変です。MemtableからSSTableへの書き込みがされたら、アプリケーションからは変更できません。CompactionだけがSSTableのディスク上の構造を変更できる唯一の手段です。JSON形式でのインポートまたはエクスポートするには、org.apache.cassandra.tools.SSTableImporterとSSTableExporterをチェックしてください。
- Stage
Cassandraでは一部SEDAを利用して、処理の基本単位をStageとしてラップしています。StageはCassandraの性能を左右する重要な要素です。一つの操作は一つのスレッドで完結する場合よりも、むしろ複数のStageを経由して完了することになるでしょう。Stageはイベントキュー、イベントハンドラとそれに結び付けられたスレッドプールで成り立ちます。Stageはスレッドのスケジューリングとアロケーションを決定するコントローラによって管理されます。Cassandraではjava.util.concurrent.ExecutorServiceを利用してスレッドプールを使った並列実行モデルを実装しています。より詳細な情報はorg.apache.cassandra.concurrent.StageManagerクラスを参照してください。次に示す処理がCassandraではStageとして実装されています。
Read,Mutation,Gossip,Response,Anti-Entropy,Load Balancer,Migration,Streaming
他にもいくつかStageとして実装されているものがあります。ColumnFamilyStoreクラス内のMemtableと協調動作するところや、StorageService内のConsistencyManagerです。操作は複数のスレッドを経由して実行されます。スレッド間の連携は当該スレッド同士で直接は行われませんが、複数のStageをまたいで実行されます。SEDAも参照してください。
- Strong Consistency
読み込み系の操作で、修復の必要性(一貫性がない場合)を検知した場合に、まずReadRepairを実行して、それから結果を返します。
- SuperColumn
SuperColumnは値がStringではなく、Column集合の写像です。この場合、Column集合はSubcolumnsと呼ばれます。Subcolumnsは順序付けされており、写像するColumnの数に制限はありません。タイムスタンプを持たない点でも他の通常のColumnとは違います。SuperColumnは再帰的には利用できません。一階層までしか利用できないという事です。通常のColumn群の写像をもてるだけで、SuperColumnの写像はできません。SuperColumnはIColumnと、IColumnContainerインタフェースを実装したSuperColumn.javaで定義されています。このインタフェースは次のような機能を提供します。名前から一つのSubcolumnを取得したり、Subcolumnを追加したり、削除したり、SuperColumn内のSubcolumnの数をチェックしたり、Subcolumnの最終更新時間をチェックしたりなど様々です。SuperColumnはオリジナルのBigtableにはないFacebookによって加えられた更新の一つです。
- Thrift
ThriftはCassandraサーバと通信するためのRPCクライアントです。様々な言語向けのインタフェースを静的に生成します。C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk, やOCaml等です。これによりこれら複数の言語でCassandraと通信することが可能になります。Thriftは2007年にFacebookで開発され、2008年3月にapacheのincubatorプロジェクトに寄与されました。この原稿の執筆時(2010年5月)では、Thriftはより新しく、より活発なApacheProjectのAvroに置き換えられています。Avroは静的なコード生成が必要ありません。Thriftについての詳細はhttp://incubator.apache.org/thriftのプロジェクトページを読んでください。
- Timestamp
Cassandraでは、タイムスタンプはクライアントが付与するので、クライアントのシステムクロックを同期させておかねばなりません。タイムスタンプはUnixepochからの経過ミリ秒単位で表されます。
- Token
クラスタ内のそれぞれのノードは格納するデータのKey範囲を決めるためのTokenを保持しています。これはクラスタ内の直前のノードのTokenによって決められます。Tokenの値はPartitionerに依存します。RandomPartitionerではTokenは0~2の127乗の範囲内の整数値になります。これはKeyのMD5を適用することで生成されます。org.apache.cassandra.dht.BigIntegerTokenクラスで実装されています。OrderPreservingPartitionerではTokenはKeyに基づいたUTF-8のStringです。org.apache.cassandra.dht.StringTokenクラスで実装されています。Tokenはorg.apache.cassandra.dht.Tokenで実装されています。
- Tombstone
Cassandraではパフォーマンスを考慮して、削除操作をしてもすぐにデータは削除されません。かわりにデータに、すでに削除されたにも関わらず、実は完全には削除されていない事を示す"tombstone"がマークされます。"tombstone"は他のレプリカに伝播されます。"tombstone"はメジャーCompactionで削除されます。
- Vector Clock
(訳者脚注:少々わかりずらいので、アルゴリズムの詳細を知りたい方はhttp://funini.com/kei/logos/clock.shtmlを参照してください)
※VectorClockによるイベントの同期機構は0.7で取り込まれる予定
- Weak Consistency
読み込み系の操作で、一番最初に帰ってきた値を返すことで高いパフォーマンスを提供します。この後に必要に応じてReadRepairを実行します。