👁️

NoSQLデータベース、Cassandraの概要と利用上の注意点

2021/03/31に公開

最近Cassandraを触る機会が増えてきており、利用していく上で学んだことを自分なりにまとめてみます。
※こちらは社内勉強会用に作った資料です。

Cassandraの概要

CassandraはFacebook社が2008年にOSSとして公開し、2009年にApacheのプロジェクトとなりました。

以下の様な特徴があります。

  • Key Value Store(KVS)構造をもつ分散型のデータベース。
  • 複数ノードで構成されており、Partition Key[1]によってデータが分散される
  • データは各ノードに分散されているが、可用性のためデータのレプリカを別のノードにも保持する
  • 結果整合性を採用しており、Consistency Level[2]によって整合性を調節できる
  • トランザクションは存在しない(ただし、軽量トランザクションがあるにはある)

Node

1. Partition Key

Partition Keyとは、Cassandraが各ノードにデータを分散配置する際に使用される値です。
以下のように、RDBと似た書き方で指定できます。この場合 id がPartition Keyとなります。

CREATE TABLE users (
   id int,
   name text,
   birth timestamp,
   PRIMARY KEY (id)
);

2. Consistency Level

Cassandraは結果整合性を採用しており、CAP定理においてAPを採用しています。
Consistency Levelとは、整合性の段階を調節する値であり、CONSISTENCYコマンドで設定することができます。

Cassandraのデータ取得の流れを説明すると、

  1. Cassandraはデータが入ってるノードに対してリクエストを送る
  2. リクエストを受けたノード(コーディネータ)が他ノードにレプリカを問い合わせる
  3. データが存在することを確認(整合性を担保)し、ノード(コーディネータ)がデータを返す

という流れになります。

そのため、他ノードにレプリカを問い合わせる分レスポンスは遅くなりますが、データの一貫性を大半の場合担保できます。
Consistency Levelは、整合性のレベルを調節することで、整合性・可用性のバランスを取ることができます。
Consistency Level一覧

Cassandraを使うメリット、デメリット

メリット

  • Master-Slaveの概念がないので、どこかのノードがダウンしてしまっても問題なく処理を続けることが可能。
  • ノードの追加・削除が簡単に行えるので、スケールがしやすい。
  • 大量のリクエストの処理(ただし、単純なクエリに限る)

デメリット

  • 整合性の担保はできない(Consistency Levelによって調節は可能)
  • 複雑なクエリは苦手

利用する上での注意点

こちらではCassandraを調査して学んだことや、使用してみて詰まったことから学んだ注意点を上げたいと思います。

1. ALLOW FILTERINGオプションの使用

Cassandraはデータを取得する際に、基本的にはPartition Keyを指定してアクセスします。もしPartition Keyを指定せずにアクセスする場合はALLOW FILTERINGオプションをつける必要があります。

SELECT *
FROM users
WHERE birth=1615459001
ALLOW FILTERING;

ただし、Partition Keyを指定せずにデータを取得する場合Cassandraは複数のパーティションをまたいで検索しにいくことになるため、クエリの処理に時間がかかり、システムのパフォーマンスが落ちてしまいます。
そのため、ALLOW FILTERINGは開発時のみ使うようにして、データモデルを変更するなりして基本的にALLOW FILTERINGオプションは使用しないようにします。

2. Partition Keyの複合指定

CassandraはPartitiok Keyをベースにデータが各ノードに分散されるので、Partition Keyは適切に分散するよう一意に決める必要があります。その際に2つのKeyを使って複合Partition Keyにしたいケースがあります。
Partition Keyを複合指定する場合は、以下のように設定します。
(idnameが複合Partition Keyになる)

CREATE TABLE users (
   id int,
   name text,
   birth timestamp,
   PRIMARY KEY ((id, name))
);

また、以下のように書くことでClustering Keyを設定することができます。
(idがPartition Key、nameがClustering Key)

CREATE TABLE users (
   id int,
   name text,
   birth timestamp,
   PRIMARY KEY (id, name)
);

Clustering Keyとは、パーティション内でデータのグループ化、ソートを担当するフィールドです。
Partition KeyがWHERE句で使われている場合は、Clustering KeyもWHERE句で使用することができます。

複合Partition Keyを指定する場合は、Clustering Keyの設定と混同しないように気をつけましょう。
🙆‍♂️ : PRIMARY KEY ((id, name), birth)
🙅‍♂️ : PRIMARY KEY (id, name)

3. Consistency Levelの設定

概要のセクションでConsistency Levelによって整合性レベルが調節できると書きましたが、サービスの要件によってConsistency Levelを適切に選択する必要があります。

レベル レプリカ
One 最も近いレプリカ 不整合が発生する場合があるが、速度は速い
Quorum 全てのデータセンターの過半数のレプリカ 速度は遅いが、高い整合性を担保できる
ALL すべてのレプリカ 最高レベルの整合性が担保されるが、1台でもノードが落ちるとエラーが返る
Consistency Level一覧

その中でも、ALLは単一障害時やメンテナンスによりノードが1台でもダウンしていると、リクエストが失敗するため注意が必要です。

4. データ削除におけるtombstone(墓石)の発生

Cassandraはデータ削除を行うとき、すぐに物理削除されるわけではなく削除フラグ(tombstone)が付与され一定期間後に削除が実行されます。tombstoneが発生することにより以下のような懸念点があります。

  • 短期間に大量のデータを削除するとtombstoneが大量に作成されることになり、tombstoneデータが削除されるまでストレージは増え続けます。
  • tombstone付きのデータはRead時にもアクセスされるため、データが大量に存在する場合は性能低下が起こり得ます。
  • 一定数(デフォルト10万)のtombstoneがストレージに存在する場合、クエリがエラーによって失敗するようになります。

上記の懸念点より、大量のtombstoneが発生することはパフォーマンスに影響を与えるので避ける必要があります。

対処方法

1.大量のデータ削除は避ける

なるべくデータが削除されないようなテーブル設計にするべきであり、どうしてもデータが大量に削除される場合はCassandraを使うべきではないです。

2.カラムにnullをinsertするのを避ける

Cassandraに明示的にnullをinsertすると、tombstoneが発生するので注意する必要がある。

INSERT INTO USERS (ID, name, birth) VALUES('id', 'name', null);

また、空配列もnull扱いになるので注意

INSERT INTO HASHTAGS (ID, USERID, HASHTAGLIST) VALUES('id', 'userID', []);

※ただし、こちらも定期削除でtombstoneは消える

3.アラートの検知

Cassandraにはtombstoneの値が閾値(デフォルト1000)を超えた時にアラートを挙げる機能がありますtombstone_warn_threshold
この値はCassandra.ymlに書かれており、設定したらノードを再起動させることで設定が反映されます。この検知を上手く使うことでクエリーの停止や性能悪化を回避することが出来ます。

まとめ

ここまでざっとですがCassandraの概要と利用上の注意点を上げてみました(この他にも注意点はあります)。Cassandraはスケールのし易さや大量のリクエスト処理が売りであり、プロジェクトによってはかなりのパフォーマンスを発揮すると思います。ただ、利用する上で注意点がいくつかあるので安易に導入するのではなく、他のDBと比較して用件に合っているかどうかを見極める必要があります。

Discussion