Open7

cassandraを学ぶ

バタンヌバタンヌ

学ぼうと思った経緯

転職先で、ポリグロット永続化をしていた。cloudSQL(MySQL),cassandra,elasticsearch,radisなど多種多様なデータストアを使用していたので、まずはcassandraから勉強しようと思った(今までRDBMSしか使ってこなかった)。

バタンヌバタンヌ

cassandraについて

Facebookが自社の大規模DBを管理する為に開発。今は、Apache Foundationが管理しているオープンソースのNoSQLデータベース。

以下公式サイト
https://cassandra.apache.org/_/index.html

一言で表現すると、
「パフォーマンスを損なうことなくスケーラビリティと高可用性を実現できる、オープンソースのNoSQL分散データベース」

バタンヌバタンヌ

特徴

  • 分散アーキテクチャ
    データはクラスタ全体に分散保存されます。
    特定のサーバに依存せず、全ノードが対等な「P2P(ピア・トゥ・ピア)」構成。
    (→ブロックチェーンと同じ考え)

    • ノード:データサーバー
    • クラスタ:ノードの集合体
  • スケーラビリティ
    ノードを追加すればほぼ増やした台数に比例してスケールアウト可能。
    数百 TB〜PB級のデータにも対応。

  • 高可用性
    ノード障害が起きてもデータは自動でレプリケーションされる。
    ダウンタイムなしで運用できる。

  • 柔軟なデータモデル
    RDBのように固定スキーマではなく、Key-Value型+カラム指向(Wide Column Store)のデータモデル。

    • Key-Value型→ノードにvalue(レコード)のキーを紐づけているので読み書きが高速
    • カラム指向(Wide Column Store)→ バリューはRDBのようにカラム数に制約はなく、データ行ごとに持っている列の数や内容が異なってもOkという考え方
Key: ユーザー123
Value: {名前: "田中", メール: "tanaka@mail", 電話: "090-1111", 住所: -}

Key: ユーザー124
Value: {名前: "田中", メール: "tanaka@mail", 電話: - , 住所: "福岡県" }
  • チューニング可能な一貫性モデル
    書き込み・読み込みごとに「一貫性レベル」を選択できる。
    QUORUM (過半数確認), ONE, ALL など。
    例)
    • SNSの「いいね」数 → 少しずれててもOK → ONE
    • 銀行の残高 → 絶対に正確にしたい → ALL
バタンヌバタンヌ

RDBとの比較

  • RDBはBツリー構造で順番に枝を辿るので、データ量が大きくなればなるほど処理時間も増える。cassandraはキーバリューストアなので、ノードのどの場所に格納されているかをキーで一発で引っ張ってこれるので、データが増えても処理時間はほぼ変わらない。
  • RDBはマスターサーバーが落ちると、一時的にアクセス不可になる。
  • レプリカを作る設定もあるが、cassandraより複雑らしい
  • RDBは列の構造が固定されている。
    • 新しい情報を追加したいときは ALTER TABLE で列を追加する必要がある。
    • しかし大規模データの場合、この操作が重くなる。Cassandraは 行ごとに持つ列を自由に変更可能
      Aさんは電話番号だけ、Bさんは住所だけ、Cさんは名前だけ…でもOK。
    • 列が増えすぎても全体のパフォーマンスに影響が少ない
バタンヌバタンヌ

それぞれの設計思想まとめ

特徴 RDB Cassandra
データ構造 固定スキーマの表 柔軟な列構造(行ごとに違ってもOK)
一貫性 高い(ACID) 選択可能(スピード優先も可能)
スケール スケールアップ中心(1台を強化) スケールアウト中心(ノード追加で拡張)
可用性 マスター依存で停止リスクあり ノード障害でも止まらない
検索・集計 複雑な検索・JOINに強い 単純検索・Key-Valueアクセスに最適
向いている用途 銀行、会計、ERP SNS(例えばいいね数など)、IoT、ログ、広告配信
  • RDB
    データの関係性を明確に管理し、整合性は悲観的な考え。
  • ccasandra
    大量データを止まらずに高速に扱うサービスが得意だが、整合性は楽観的な考え。よく結果整合性という表現をされる(最初はデータが完全に一致していなくても、時間が経てば最終的に全ノードのデータが揃うことが保証されている)。
バタンヌバタンヌ

疑問に思ったこととその答え

JOINが難しい理由はなんで?

answer
例:SNSユーザー情報と投稿情報を結合
ユーザー情報はノードA、投稿情報はノードB、ノードCにもレプリカあり
JOINするときは 複数ノードのデータを集めて、結合して、さらに整列 する必要がある
これを分散環境でやると:

  • ノード間通信が発生 → 遅くなる
  • 障害があると一貫性が崩れるリスク
  • そもそもCassandraは「単純なKey-Value検索」を高速化する設計なので、JOINは想定外

じゃあ、そもそも1レコードにJOINした状態で最初から定義しておけばいいじゃん

answer
例:

  1. ユーザー情報 + 投稿情報を1つのレコードにまとめる
  2. 「ユーザーID → その人のプロフィール+全投稿」と1つに格納
    一見、JOIN不要で高速アクセスできそうです。

[問題点]
データ量が膨大になると、ノードの負荷が高くなるため。

  1. 投稿が増えるたびに 1つのレコードが巨大化
  2. 巨大レコードを読み書きするとノード負荷が高くなる。
  3. また複数ノードにコピー(レプリケーション)されている場合、更新のたびに全コピーを同期する必要がある

Cassandraは「書き込み高速・分散に強い」設計ですが、巨大データの更新は負荷が大きく遅くなってしまう。→分散型にしている意味がなくなる。