0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Cassandra】データ整合性を維持するオペレーション

Last updated at Posted at 2024-09-10

はじめに

Cassandraである程度一貫性を担保して運用していくためには、実施すべきオペレーションがいくつかあります。
この記事では整合性に関連するCassandraの概要とデータ整合性維持に重要なオペレーションをいくつか紹介します。

Cassandraの概要

Cassandraと整合性

Cassandraでは 可用性(Availability)分断耐性(Partition-tolerance) を実現するために 一貫性 (Consistency) として 結果整合性(Eventual Consistency) を採用しています。

Cassandraの読み書き

Keyspace単位で設定された REPLICATION にしたがって特定のデータを担当するノードを決定します。production環境では論理DCごとにレプリカ数を設定する NetworkTopologyStrategy が推奨されています。

CREATE KEYSPACE example 
  WITH REPLICATION = { 
   'class' : 'NetworkTopologyStrategy', 
   'dc1' : 3,
   'dc2' : 3,
} ;

consistency level

REPLICATION によって決定された担当ノードの中から consistency level に設定されたノード数のread/writeが成功すればクライアントに正常な結果を返すように設定することができます。
一貫性を重視した設定をすることでデータ整合性をある程度担保することが可能ですが、その分可用性が失われるため、ユースケースに応じた設定が必要です。
以下が代表的なものになります。

  • ONE: 最初に返却したノードのデータをクライアントに返します
  • QUORUM: 最初に返却した (レプリカ数/2)+1、つまり過半数のノードのデータを中から最新のものをクライアントに返します
  • ALL: 全てのノードのデータの中からTimestampが最新のものをクライアントに返します

設定できるLevelの詳細についてはこちらなどを参考にしてください。

Cassandraと削除

削除を実施した場合、tombstone という削除データを書き込むことで論理削除を行なっております。readした最新データがtombstoneであった場合、削除されたデータとしてクライアントに返却されます。


ここまでがCassandra概要になりますが、read/writeともに QUORUM などの一貫性を重視した consistency levelを設定していた場合でも、適切な運用を実施していない場合には予期しないデータを返却してしまうケースも存在します。
今回はCassandraの整合性を維持する上で必要とされる運用オペレーションをいくつか紹介いたします。

整合性維持のためのオペレーション

Repairの実施

ノード間のデータを比較し、全てのノードのデータを最新データへと修復するコマンドです。

# データ全体をRepairしたい場合

# 全台に実行する場合
$ nodetool repair --full -pr

# 1ラックに実行する場合
$ nodetool repair --full

コマンドに指定するオプションよって実行が必要なノード数や時間が異なるため、詳細についてはこちらなどを参考にしてください。
tombstoneもこちらのコマンドによって同期されます。

Repair未実施による不整合

削除データの復活

tombstoneが削除されるタイミングはTABLEオプションgc_grace_seconds にて指定が可能で、デフォルトは864000秒(10日)に設定されています。
しかし、Repairがgc_grace_seconds時間以上未実施の場合には、tombstoneのwriteに失敗しているノードが存在する場合にデータが復活します。

gc_grace_seconds経過前

過半数の2ノードでtombstoneが存在しているため、QUORUMでreadを行った場合、データ1は削除されているデータとしてクライアントに返却されます。
repair_before.png

gc_grace_seconds経過後

gc_grace_secondsが経過すると、node1とnode2ではCompaction実行時にtombstoneとデータ1が物理削除されます。
しかし、node3についてはtombstoneが存在しないため、物理削除が行われずにデータ1が残ったままになってしまいます。これによりnode3から返却された場合は消したはずのデータが復活してしまう事象が発生します。
また、その後にRepairが実行されると全てのノードへデータ1が伝播するため、全てのリクエストでデータが復活することになります。
repair_after.png

以上のようなRepair未実施によるデータ復活を防ぐため、
gc_grace_seconds経過前にRepairを実行することで、tombstoneを全てのレプリカノードに同期させておく必要があります

Cleanupの実施

クラスタへのノードの追加や削除により担当するデータの範囲に変更があった場合に、すでに担当ではなくなった不要データを該当ノードから削除するコマンドです

# すべてのkeyspace/tableに実行する場合
$ nodetool cleanup

Cleanup未実施による不整合

古いデータの読み込み・削除データの復活

Cleanupを実施しないまま担当データ範囲に変更があった場合に、該当ノードでの古いデータの読み込みや削除データの復活をする場合があります。

ノード追加前

まずはnode1, node2, node3にデータ1が存在している状態です。
before_add.drawio.png

ノード追加後

node4が追加されたことにより、データ1の担当がnode3からnode4へ変更され、
node3では物理データはあるが参照されないようになります。
after_add.drawio.png

データ削除

データ1の削除が実施されnode1, node2, node3からデータ1が削除されます。
node3はデータが残ったままですが、データ担当範囲ではなく参照されないため、データ1はクライアントには削除状態が返却されます。
after_delete.drawio.png

ノード削除後

node4がクラスタから削除された場合、node3が再びデータの担当範囲になるためデータ1がクライアントから参照されるようになってしまいます。
after_redelete.drawio.png

以上のようなCleanup未実施によるデータ復活や該当ノードに対する古いデータのreadを防ぐため、
ノード追加を実施の際にはCleanupを実行する必要があります

Ring情報を一致させる

クラスタの Token Ring(データ担当範囲)情報 を表示するコマンドです

# すべてのkeyspaceに実行する場合
$ nodetool ring

Ring情報の伝播について

CassandraではRing(データ担当範囲)情報を Gossip を使ってやりとりしています。

Gossip

クラスタに属する各エンドポイントのメタ情報を拡散しています。
各ノードは定期的にクラスタ内の他のノードをランダムに選定してやりとりを行い、ハートビートの世代数を確認して更新が必要であればメタ情報の更新を行います。非常に素早く情報を伝播させることができますが、変更順序を厳密に保証していないため、問題を発生させる場合があります。

Ring情報ずれによる不整合

GossipではRing情報のやりとりも行っており、ノード間でRing情報がずれることで読み書きの不整合が発生します。Ring情報のノード間差分を監視することでデータ不整合の発生可能性の検知を行うことができます。
以下がデータ不整合の一例です。

クラスタ内で以下の2つのRing情報が混在している場合
latest_ring_before.drawio.png
このような場合にnodeBを含むRingAを認識しているCoordinatorノードが最新のデータをnodeBに書き込んだ後、nodeBを含まないRingBを認識しているCoordinatorノードがデータを読み込むとnodeAから古いデータを読み込むことで一部データの不整合が発生します。

※ Cassandra 5.xではGossipから Transactional Cluster Metadata(TCM) での管理が行われるため、こうした不整合の解消が予定されております。

以上のようなRing情報ずれによる該当ノードに対する古いデータのreadを防ぐため、
ノード間のRing情報を定期的に監視し、差異が発生していた場合にはノードの再起動などでGossipの再伝播を行う必要があります

ダウンノードの起動

ノードがダウンしていた際に Hinted Handoff によって復旧時にデータが再送信されることによりデータの一貫性を確保します。

Hinted Handoff

cassandra.yamlによって hinted_handoff_enabled を有効化することで、書き込みのデータ担当となっているノードがダウンした場合にCoordinatorノードで一時的に書き込みを保管し、復旧する際にノードへデータを再送信することでデータの一貫性を確保します。

ダウン時の書き込み欠損

Hinted Handoffを有効化した場合も注意が必要になります。Hinted Handoffは max_hint_window_in_msを超過したデータについてはCoordinatorで保持されなくなるため、max_hint_window_in_msを超過した場合に整合性を維持するためにはダウンノードに対するRemovenodeReplaceといった対応が必要になります。

※ Schema versionが異なるバージョンアップ時には、デプロイ後の起動でHintの伝播をしないため注意が必要になります。

最後に

ここで紹介した以外にも注意すべき事項などはあると思いますが、皆さんのCassandra運用の一助になればと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?