# Cassandra — A Decentralized Structured Storage System
> [!abstract]
> Cassandra は、Facebook が開発した分散構造化ストレージシステムであり、大量の構造化データをコモディティサーバ群に分散配置しつつ、単一障害点のない高可用サービスを提供する。データモデルは [[Bigtable|[[@2006__OSDI__Bigtable - A Distributed Storage System for Structured Data]]]] のカラムファミリモデルに由来し、パーティショニングとレプリケーションの設計は [[Dynamo|[[@2007__SOSP__Dynamo - Amazon's Highly Available Key-value Store]]]] の手法を踏襲する。書き込みスループットの最大化と読み取り効率の両立を主目標とし、Facebook Inbox Search(1 億ユーザ超)を本番稼働させた実績を持つ。
## 論文情報
| 項目 | 内容 |
|---|---|
| タイトル | Cassandra - A Decentralized Structured Storage System |
| 著者 | [[Avinash Lakshman]]、[[Prashant Malik]] |
| 所属 | [[Facebook]] |
| 発表 | LADIS 2009(Workshop on Large Scale Distributed Systems and Middleware)、ACM SIGOPS Operating Systems Review 44(2), 2010 |
| URL | https://dl.acm.org/doi/10.1145/1773912.1773922 |
## 概要
Cassandra は、数百〜数千台のコモディティサーバ上で大規模な構造化データを管理する分散ストレージシステムである。完全なリレーショナルデータモデルを提供せず、動的なデータレイアウトとフォーマット制御を備えた単純なデータモデルを採用する。設計上の主要な影響源は 2 つあり、Dynamo からはコンシステントハッシュによるパーティショニング、クォーラムベースのレプリケーション、ゴシップベースのメンバーシップ管理を継承し、Bigtable からはカラムファミリ・スーパーカラムファミリのデータモデルと、コミットログ + メモリ上テーブル + SSTable による永続化パイプラインを継承している。
## 問題設定
Facebook は数億のユーザに対してピーク時に数万台のサーバでサービスを提供しており、常に一定数のサーバやネットワークコンポーネントが障害状態にある。この環境で Inbox Search 機能を実現するためには、以下を満たすストレージ基盤が必要であった。
- 1 日あたり数十億件の書き込みを処理する高い書き込みスループット
- 地理的に分散したデータセンタ間でのレプリケーション
- ユーザ数の増加に対するリニアなスケーラビリティ
- 構成要素の障害を常態として扱う耐障害設計
既存の選択肢のうち、リレーショナルデータベースは強一貫性の保証がネットワーク分断時の可用性を犠牲にし、Dynamo はベクトルクロックの書き込み前読み取りが高書き込みスループット環境では制約となり、Bigtable は分散ファイルシステム(GFS)に依存するため独立したデプロイが困難であった。
## 提案手法
### データモデル
Cassandra のテーブルは、キーによって索引付けされた分散多次元マップである。行キーに対する操作はレプリカ単位で原子的に実行される。カラムはカラムファミリとしてグループ化され、[[@2006__OSDI__Bigtable - A Distributed Storage System for Structured Data]] のカラムファミリと類似した構造を持つ。さらにスーパーカラムファミリ(カラムファミリの入れ子)を導入し、カラムの時刻順・名前順ソートを提供する。
### パーティショニング
[[一貫性ハッシュ法]](consistent hashing)によりデータをクラスタ全体に分散する。各ノードにはリング上のランダムな位置が割り当てられ、キーのハッシュ値から時計回りに最初に見つかるノードがコーディネータとなる。Dynamo の仮想ノード方式ではなく、負荷情報に基づきノードがリング上を移動する方式を採用し、負荷分散の決定論性を確保した。
### レプリケーション
各データ項目はレプリケーションファクタ N に従い N 個のノードに複製される。レプリケーションポリシーとして「ラック非対応」「ラック対応」「データセンタ対応」の 3 種を提供し、Zookeeper を用いたリーダ選出でレプリカの範囲割り当てを管理する。データセンタ間レプリケーションにより、データセンタ全体の障害にも耐える。書き込みはクォーラム数のレプリカから応答を得て完了とし、読み取りは要求される[[結果整合性]]レベルに応じて最も近いレプリカまたは全レプリカにルーティングされる。
### メンバーシップと障害検知
クラスタメンバーシップは Scuttlebutt に基づく[[ゴシッププロトコル]]で管理される。障害検知には Φ 累積障害検知器(Φ Accrual Failure Detector)の改良版を採用した。従来のブーリアン判定ではなく、疑念レベル Φ を連続値で出力し、Φ = 1 で誤検知確率約 10%、Φ = 2 で約 1% となる。ゴシップメッセージの到着間隔を指数分布で近似し(原論文のガウス分布ではなく)、ネットワーク・負荷条件に動的に適応する。100 ノードクラスタにおいて、従来の障害検知器が 2 分要した検知を Φ = 5 の保守的設定で平均 15 秒に短縮した。
### ローカル永続化([[LSMツリー]]型パイプライン)
書き込みは以下のパスを経る。
1. **コミットログ**への逐次書き込み(専用ディスク)— 耐久性と復旧を保証
2. **メモリ上データ構造**(メムテーブル)への更新
3. 閾値超過時にメムテーブルを**SSTable** としてディスクにフラッシュ(逐次書き込み、インデックス付き)
4. バックグラウンドの**コンパクション**により複数 SSTable をマージ(Bigtable のコンパクションと同様)
読み取りではまずメモリ上構造を参照し、ヒットしなければ新しい順にディスクファイルを走査する。各ファイルにはブルームフィルタが付随し、不要なディスクアクセスを回避する。256 KB 境界ごとのカラムインデックスにより、目的のカラムへの高速ジャンプを実現する。すべてのディスク書き込みは逐次的であり、ファイルは不変(ミューテーションなし)であるため、読み取り時にロックが不要であり、事実上ロックフリーの読み書き操作が可能である。
### 実装
Java で実装され、SEDA アーキテクチャに基づくイベント駆動パイプラインを持つ。制御メッセージは UDP、レプリケーションとルーティングは TCP を使用する。ノード追加時のデータ転送は単一ノードから 40 MB/秒の転送レートを実測した。
## 新規性
- Dynamo のパーティショニング・レプリケーション設計と Bigtable のカラムファミリデータモデルを**明示的に統合**した最初のシステムの一つであり、両者の弱点(Dynamo のベクトルクロック書き込み前読み取り、Bigtable の GFS 依存)を回避した
- Φ 累積障害検知器を[[ゴシッププロトコル]]環境に初めて適用し、到着間隔を指数分布で近似することで精度と速度を改善した
- データセンタ対応レプリケーションにより、地理分散環境での完全非中央集権ストレージを実現した
## 実験設定
- Facebook Inbox Search:1 億ユーザ超(論文時点で 2.5 億ユーザに拡大)
- 150 ノードクラスタ、米国東西海岸のデータセンタに分散配置
- 50 TB 以上のデータを格納
- 障害検知実験:100 ノードクラスタ
## 実験結果
### Inbox Search の本番レイテンシ
| 統計量 | Search Interactions | Term Search |
|---|---|---|
| 最小 | 7.69 ms | 7.78 ms |
| 中央値 | 15.69 ms | 18.27 ms |
| 最大 | 26.13 ms | 44.41 ms |
### 障害検知
- 従来の障害検知器:100 ノードで障害検知に約 2 分
- Φ 累積障害検知器(Φ = 5):同条件で平均 15 秒
### データ移行
- MySQL から 7 TB のインデックスデータを MapReduce で変換し Cassandra に投入
- 単一ノードからのデータ転送レート:40 MB/秒
## 考察
Cassandra の設計は、当時の分散ストレージにおける 2 つの主要アプローチ —— Dynamo 型の完全非中央集権キーバリューストアと Bigtable 型の構造化ストレージ —— のハイブリッドであり、両者の長所を取り込みつつ短所を回避している。特に、ベクトルクロックを排除しタイムスタンプベースの衝突解決を採用したことで書き込みパスが単純化され、高書き込みスループットが実現された。一方、この選択はタイムスタンプの精度に依存するため、クロック同期の精度が書き込みの正確性に直結する。
Zookeeper をリーダ選出に使用している点は「完全非中央集権」という主張とやや矛盾するが、著者自身も「一定の協調機構は分散機能の実装を容易にする」と述べており、実用上の妥協として位置づけている。
## 強み
- 書き込みパスの単純さ(コミットログ → メムテーブル → SSTable)による高スループット
- データセンタ対応レプリケーションによる地理分散高可用性
- Φ 累積障害検知器による適応的で高速な障害検知
- 1 億ユーザ超の本番環境での実証
## 弱点・課題
- キー間のトランザクションやセカンダリインデックスが未サポート(論文時点)。著者は将来の課題として言及
- タイムスタンプベースの衝突解決はクロック同期の精度に依存し、同時書き込みの意味論が不明確
- 定量的なベンチマーク評価(スループット、スケーラビリティの体系的測定)が不足しており、Inbox Search の運用数値のみ
- スーパーカラムファミリの設計は後に廃止される(Apache Cassandra 3.x 以降)
- 論文で述べられた圧縮機能の追加は未実装であった(後のバージョンで実現)