cassandraのしくみ データの読み書き編
DESCRIPTION
4/28 Cassandra勉強会資料TRANSCRIPT
- データ読み書き編 -
2010/4/28 Cassandra 勉強会@yukim
の仕組み
翻訳者募集中 !
森下 雄貴@yukim
Cassandra wiki 翻訳に参加してますhttp://wiki.apache.org/cassandra/FrontPage_JP
= Bigtable + Dynamo + α
Bigtable + α のリッチなデータモデル
Keyspace
ColumnFamily
Column Column Column
Column Column Column
Column Column Column
Key
Key
Key
ColumnFamily
Column Column Column
Key
Key
SuperColumn
Column Column Column
SuperColumn
Column Column Column
SuperColumn
Column Column Column
SuperColumn
Dynamo をベースとした P2P の分散ハッシュテーブルキーを元に計算されたトークンがどのレンジに属するかによって、データを保持するノードが決まる。
A
D
G
K
O C
Dynamo をベースとした P2P の分散ハッシュテーブルレプリケーション戦略に基づいたデータのレプリカを保持する。Eventual Consistent
A
D
G
K
O C
Cassandra はどのノードに対しても読み書き可能。 SPoF なし。
Dynamo をベースとした P2P の分散ハッシュテーブル
操作ごとに制御可能な一貫性レベル
ZEROANYONEQUORUM(N/2 + 1)
ALL
ZEROANYONEQUORUM(N/2 + 1)
ALL
ReadWrite
W + R > NW: 書き込み時のレベルR: 読み込み時のレベルN: レプリカ数
強い一貫性が得られる
現時点で最新の 0.6.1 をベースに
今日は書き込みと読み込みの話Cassandra の読み書きの仕組みを紐解いてみる
書き込み編
クライアントは一貫性レベルを指定して、データの書き込み( 登録 / 更新 / 削除 ) 要求をクラスタ内のノードに送信。要求を受けたノードは、どのノードにデータを保持するかを決定し、要求をフォワードする。
insertbatch_mutateremove
書き込み要求
データを保持するノードへ要求をフォワード
書き込み要求1. トークンを計算し、データを保持するノードを決定2. レプリケーションを保持するノードを決定3. Hinted Handoff の必要性を検証
一貫性レベルに応じて挙動がかわる。
を行い書き込み要求をフォワードするノードを決定。 ( ローカルの場合もある )
ZERO非同期でフォワードを行う。クライアントにすぐ返るが、何も保証されない。
ANY 以上指定された一貫性レベルの数だけフォワード先からレスポンスが返った場合のみクライアントにレスポンスを返す。どこかでエラーが発生したら TimeoutException 。
1. トークンを計算し、データを保持するノードを決定
<Partitioner> org.apache.cassandra.dht.RandomPartitioner</Partitioner>
プラッガブル
パーティショニング方法 (IPartitioner の実装 ) に基づいてどのノードに属するデータかを決定
RandomPartitionerキーの MD5 ハッシュを元にトークン生成。
OrderingPreservedPartitioner CollatingOrderPreservingPartitioner
2. レプリケーションを保持するノードを決定レプリケーション戦略
RackUnawareStrategy RackAwareStrategy DatacenterShardStrategy
こちらもプラッガブル<ReplicaPlacementStrategy> org.apache.cassandra.locator.RackUnawareStrategy</ReplicaPlacementStrategy>
3. Hinted Handoff の必要性を判定
ノード故障の判定
本来そのデータを保持するはずだったノードの情報( Hint) をつけて、別のノードにそのデータを格納しておく。
Hinted Handoff を受けとったノードは本来保持するノードのアドレスを SYSTEM テーブルへ保持。
Hinted Handoff
“ϕ accrual failure detector” - ϕ 漸増型故障検出器
書き込み要求を受け取ったノードでは…
CommitLog
Memtable
SSTable
フラッシュ (flush) => 非同期
メモリ上
ディスク上
設定 ( デフォルト :128MB) されたサイズに到達するとログがローテートされる
コミットログヘッダ
RowMutation + チェックサム (CRC32)
CF ごとのダーティフラグ
CF ごとのファイルポジション
リプレイを開始するポジション
リプレイが必要かCommitLog セグメント
CommitLog
すべての書き込み操作 (RowMutation) を記録。 すべての ColumnFamiliy の Memtable が SSTable に書き込まれ
たら削除される。 ノード起動時に CommitLog があればリカバリーが実行される。
リカバリー後は強制フラッシュされ、一旦 CommitLog はクリア。
RowMutation + チェックサム (CRC32)
RowMutation + チェックサム (CRC32)
periodic ( デフォルト )• CommitLog への書き込みは待たず、 Memtable へ書き込みに行
く。• <CommitLogSyncPeriodInMS> で指定されたミリ秒ごとに Co
mmitLog への書き込みバッファをデバイスへ書き込み。 batch
• CommitLog への書き込み完了を待ってから、 Memtable へ書き込みに行く。
• <CommitLogSyncBatchWindowInMS>???
<CommitLogSync>
CommitLog
<CommitLogDirectory>
<CommitLogRotationThresholdInMB>
CommitLog をローテートする閾値
CommitLog を保持するディレクトリ
Memtable
Key
Column Column Column
Token でソート
カラム名でソート
Memtable
メモリ上のデータモデル。 ColumnFamily ごとに保持されている。
(Token, Key)
ColumFamily
(Token, Key)
(Token, Key)
OrderPreservingPartitioner のみキーでのソートが保証される
Memtable
<MemtableThroughputInMB>
<MemtableFlushAfterMinutes>
<MemtableOperationsInMillions> フラッシュされるまでの閾値。
保持されるカラム数の最大値 ( デフォルト : 0.3)
フラッシュされるまでの閾値。Memtable に対して行われた操作の総データ量 ( デフォルト : 64)
フラッシュされるまでの閾値。この時間がたってもまだフラッシュされていなければ強制フラッシュ。 本番環境では多めに設定しておいたほうが良い。 ( デフォルト : 60)
Memtable が閾値を超えると、 非同期で Memtable の内容がディスクに書き出される。その際 Bloom Filter 、 Index が一緒にディスクに書き出される。
一度書き出したら不変。コンパクション (Compaction) で複数の SSTable を 1 つにまとめられる。
SSTable
Bloom Filter
Index
DataMemtable の内容が格納されたデータファイル。
あるキーがデータファイルに存在するか ( ただし偽陽性 ) をコンパクトに知るためのファイル。
( おそらく ) キーに対応するデータの位置を保存。
マイナーコンパクション同じ程度のサイズの SSTable を 1 つにまとめる。
メジャーコンパクション1 つにマージ。
コンパクション (Compaction)
2 種類のコンパクション
ディスクの残りに注意すべての SSTable ファイルをマージして新しくファイルを作成したあと、元の SSTable ファイルを削除する。容量が足りない場合はコンパクションが行われない。 ( ログにエラー出力 )
ディスクの残量に注意 !
( 補足 ) データの削除分散環境での削除
分散してレプリカを持つため、ノードがダウンしていた場合、削除要求を受け取れない。また、同期をとってすべてのノードからデータを削除するタイミングが難しい。
Tombstone と <GCGraceSeconds>
すべてのレプリカに Tombstone フラグが行き渡っていればメジャーコンパクション時に削除される。削除要求を受け取っていないデータがある場合は、 <GCGraceSeconds> で定義された秒数 ( デフォルト :10 日 ) が経過すると削除可能と判断する。
読み込み編
読み込み要求一貫性レベルに応じて挙動がかわる。
ONE1. トークンを計算し、データを保持する一番近いノード
を決定。2. そのノードに読み取り要求を送信。3. データを受け取ったらクライアントに返す。
QUORUM 以上1. トークンを計算し、データを保持する一番近いノード
を決定。2. レプリケーションを保持するノードを決定。3. 一番近いノードにデータの読み取り要求を送信。ほか
のノードにはダイジェストのみの読み取り要求を送信。4. 一貫性レベルで指定された数のレスポンスが返ってく
るまで待つ。5. ダイジェストが一致していれば、読み取ったデータを
クライアントに返す。ダイジェストに不一致があれば実データを読み込みにいき、 Read Repair を実行。
Read Repair
読み込み時、各レプリカに違いがあった場合、最新のデータでレプリカを修復。
修復はバックグラウンドで行われる。 読み込み速度を UP したい場合は off にもできる。
(<DoConsistencyChecksBoolean>)
読み込み要求を受けたノードでは…
Memtable
SSTable
メモリ上
ディスク上
読み込み
Row Cache
Row Cache1 行分のデータをキャッシュ。たとえ 1 部のカラムの値のみの問い合わせてもすべてのカラムをキャッシュとして保持する。デフォルトではオフ。
Key Cache(0.6.0 から )SSTable 内のデータの位置をキャッシュ。
キャッシュCassandra は 2 種類のキャッシュを備える
Bloom Filter 、 Index の活用
Memtable 、 SSTable からの読み込み
すべての SSTable ファイルからあるキーを探し出す必要があるため、極力ムダを省きたい。まず Bloom Filter をチェックし、読み込む SSTable のファイルを絞り込む。
まとめ Cassandra は内部的に CommitLog 、 Memtable 、 SSTable の 3
つの物理的なデータ構造を持っている。
書き込みは CommitLog への追記 + Memtable への書き込みで終了、なので高速。
読み込み時は Memtable と全ての SSTable からデータを探すので若干遅い。けど Bloom Filter 、 Cache 等で工夫して高速化している。
内部構造を知っておいた方が環境構築にもデータモデルの設計にも運用にも役立つはず。