FAQ

CassandraはListenAddress設定で何故0.0.0.0(全アドレス)でリッスンできないのですか?

Cassandraはゴシッププロトコルベースの分散システムです. ListenAddress 設定は他ノードからこのアドレスに接続してくれというものです.
そのため,設定を0.0.0.0にして他ノードにどこでもいいからつないでくれ,というのはいまいちなアイデアです.
そういった理由から,ListenAddress設定では0.0.0.0でリッスンは出来ないです.

もし ListenAddress 設定でクラスタ上の各ノードでIPを指定したくない場合,ブランクにしておけばCassandraは InetAddress.getLocalHost() を使ってアドレスを自動的に選択します.この場合適切に動くかどうかは,ノードの名前解決が適切に動くかどうかに依存します(/etc/hostsとかです).

この仕組みの例外として,JMXがあります.JMXはデフォルトで0.0.0.0にバインドされます.これはJDKのバグです(6425769).

この詳細については,CASSANDRA-256CASSANDRA-43をご覧ください.

Cassandraはどのポートを使うのですか?

デフォルトでは,Cassandraは以下のポートを使います.

port番号

用途

7000

クラスタ間のコミュニケーション

9160

Thriftクライアント

8080

JMX

これらはどれも設定可能です.設定はstorage-config.xmlにするか,JVMオプションなどはbin/cassandra.in.shで設定できます.
全てのポートはTCPです. Cassandraを動かすには も参考にしてください.

Cassandraは何故大量のインサート後に遅くなるのでしょうか?

これはメモリ不足に起因するGCの多発から生じる症状です.メモリが不足してくるとJVMはGCを実行して十分なヒープを確保しようとしますが,GCしてもあまりヒープが解放されない場合は,短い間隔でGCが繰り返されます.いずれOutOfMemory例外でJVMがクラッシュすることになるでしょう.(通常JVMが停止する前にこのエラーを出力しますが,場合によってはこのログすら出力できない場合もあります.)

対策としては,JVMのヒープメモリの設定値を上げるか,Cassandraがmemtablesをフラッシュするまでのインサート閾値を下げてください.
詳細はMemtableThresholdsを参照してください.

キャッシュサイズを大きくしすぎるとメモリへの圧迫が大きくなる結果になります.

新たにノードを追加したときに,既存のデータはどうなってしまうのでしょうか?

新しいノードを-bオプションで開始すると,クラスタ内の既存ノードに適切なデータをコピーしてもらうように新ノードはコンタクトします.

Cassandra 0.5かそれ以上のバージョンでは,AutoBootStrapオプションが設定に追加されています.それがenableになっている場合は新規ノードは最初に起動する際に自動的にbootstrapするので,"-b"オプションは不要です.
AutoBootstrap機能を使用する場合も,InitialTokenを明示的に指定することを推奨します.InitialTokenを指定すれば,負荷分散バランスの悪いリングでも追加するノードのトークン空間上の配置を確実に制御できます.
クラスタを初期構築する場合,InitialTokenを空白のままにしたいとは思わないでしょう.構築するリングがバランスするようにトークンを選択し,各ノードに明示的に指定してください.
詳しくはWikiのトークン選択を参照して下さい.

Cassandraの内部動作を理解し,自分が何をしているかを正確に知っているのでなければ,新規の空ノードをautobootstrapを無効にしてクラスタに追加すべきでありません.write負荷がかかっている場合,0.7以降ではスキーマが新規ノードに伝搬する前にwriteが当該ノードに配送される可能性があります.これは同時に,新ノードが持っていないデータについてread要求を割り当てられることを意味します.

動いているクラスタに新たにカラムファミリを追加したり削除したり改名したりできますか?

できます.ただし手順通りに実行することが重要です.

  1. nodetool drainでコミットログを空にします.
  2. Cassandraを終了して,コミットログに残存データが無いことを確認します.
  3. 削除されたCFに対応するデータファイル(-Data.db, -Index.db, -Filter.db)を削除します.リネームされたCFのデータファイルをリネームします.
  4. storage-conf.xml (0.7以降ではcassandra.yaml)に必要な修正を加えます.
  5. Cassandraを起動すれば、変更が反映されるはずです.

参照: CASSANDRA-44

Thriftクライアントやハイレベルクライアントがどのノードに接続しているかは問題になるでしょうか?

いいえ,特に問題にはなりません.Cassandraのノードは必要に応じてリクエストをプロキシするためです.
このため,クライアントは様々なオプションの中からエンドポイントを選択する方法を選択できます:

  1. Thriftのコンタクトノードのリスト(クラスタの全ノードか,または部分)をクライアント側で管理し適切に選択するようにする.
  2. DNSのラウンドロビンを使い,コンタクトノードリストを指す共通のレコードを定義する(推奨).
  3. get_string_property("token map") RPCコールを使ってクラスタ内のノードリストを取得し、それを順次参照する.
  4. ロードバランサやプロキシなどを使う.

ハイレベルのクライアントを使用する場合は、リクエストがノード間で分散するように、そのクライアントでどのオプションが使用できるかよく調査して下さい。

### 3/15ここまで

Cassandraを動かすにはどのくらいの性能のマシンが必要でしょうか?

CassandraHardwareを参照してください.

SSTablesとMemtablesって何ですか?

MemtableSSTableMemtableThresholdsを見てください.

Javaで何故TimeUUIDTypeを使うのが難しいのでしょうか?

TimeUUIDはJavaから使うのは困難です.なぜなら,java.util.UUIDがversion 1 (time-based) UUIDをサポートしていないからです.
しかし,Javaでも以下のようにすれば使うことは可能です.

まず,このUUID generatorを使います.

以下の3つのメソッドはCassandraでUUIDを使う際に大変便利です.

TimeUUIDTypeでソートされるカラムファミリでUUIDを生成する.

	/**
	 * Gets a new time uuid.
	 *
	 * @return the time uuid
	 */
	public static java.util.UUID getTimeUUID()
	{
		return java.util.UUID.fromString(new com.eaio.uuid.UUID().toString());
	}

java.util.UUIDが簡単にbyte[]からTimeUUIDに変換する方法を持っていないため,com.eaio.uuid.UUIDにそのまま渡して処理してもらいましょう.

	/**
	 * Returns an instance of uuid.
	 * 
	 * @param uuid the uuid
	 * @return the java.util. uuid
	 */
	public static java.util.UUID toUUID( byte[] uuid )
	{
        long msb = 0;
        long lsb = 0;
        assert uuid.length == 16;
        for (int i=0; i<8; i++)
            msb = (msb << 8) | (uuid[i] & 0xff);
        for (int i=8; i<16; i++)
            lsb = (lsb << 8) | (uuid[i] & 0xff);
        long mostSigBits = msb;
        long leastSigBits = lsb;
	
        com.eaio.uuid.UUID u = new com.eaio.uuid.UUID(msb,lsb);
        return java.util.UUID.fromString(u.toString());
	}

仮にカラムの中にUUIDを入れたい場合は,以下のようにします.
このメソッドは上で示したgetTimeUUID()との結合部分になります.

	/**
	 * As byte array.
	 * 
	 * @param uuid the uuid
	 * 
	 * @return the byte[]
	 */
	public static byte[] asByteArray(java.util.UUID uuid) 
	{
	    long msb = uuid.getMostSignificantBits();
	    long lsb = uuid.getLeastSignificantBits();
	    byte[] buffer = new byte[16];

	    for (int i = 0; i < 8; i++) {
	            buffer[i] = (byte) (msb >>> 8 * (7 - i));
	    }
	    for (int i = 8; i < 16; i++) {
	            buffer[i] = (byte) (lsb >>> 8 * (7 - i));
	    }

	    return buffer;
	}

Further, it is often useful to create a TimeUUID object from some time other than the present: for example, to use as the lower bound in a SlicePredicate to retrieve all columns whose TimeUUID comes after time X. Most libraries don't provide this functionality, probably because this breaks the "Universal" part of UUID: this should give you pause! Never assume such a UUID is unique: use it only as a marker for a specific time.

With those disclaimers out of the way, if you feel a need to create a TimeUUID based on a specific date, here is some code that will work:

        public static java.util.UUID uuidForDate(Date d)
        {
/*
  Magic number obtained from #cassandra's thobbs, who
  claims to have stolen it from a Python library.
*/
            final long NUM_100NS_INTERVALS_SINCE_UUID_EPOCH = 0x01b21dd213814000L;

            long origTime = d.getTime();
            long time = origTime * 10000 + NUM_100NS_INTERVALS_SINCE_UUID_EPOCH;
            long timeLow = time &       0xffffffffL;
            long timeMid = time &   0xffff00000000L;
            long timeHi = time & 0xfff000000000000L;
            long upperLong = (timeLow << 32) | (timeMid >> 16) | (1 << 12) | (timeHi >> 48) ;
            return new java.util.UUID(upperLong, 0xC000000000000000L);
        }

Cassandraからデータを削除したのにディスク使用量は同じです.何が起こってるのでしょうか?

Cassandraに書き込まれたデータはSSTablesに書き込まれます.

SSTablesはイミュータブルで,データ削除を実行してもマーカー(tombstoneといいます)が書き込まれるだけで実際には削除されません.でも大丈夫.GCGraceSeconds後の最初のコンパクションでデータは完璧に抹消され,ディスクスペースはそのときに軽減されます.

詳しくはDistributedDeletesを参照してください.

何故書き込みより読み込みのほうが遅いのでしょうか?

メジャーなRDBMSやNoSQLシステムと違い,Cassandraはb-treeやin-placeアップデータを使っていません.
その代わりに,BigTableと同じようにsstable/memtableモデルを採用しています:ソートしディスクに書き込む前にメモリ上の構造に各カラムファミリをグループ化して書き出します.どういうことかというと,このやり方だとb-treeのようにデータを上書きするためにシークしたりディスクキャッシュ上に溜まりにたまったインデックスからシークしたりせず,書き込みでランダムIOが発生しないということです.

この方式の弱点としては,読み込みで複数のSSTablesから読み込んでマージしなくてはいけなくなる可能性があるということです.
これは十分に検討できるトレードオフだと私たちは考えています.
その理由として,

  1. スケールする書き込みは常にスケールする読み込みよりも難しい
  2. データの集合体が増加するにつれ,Cassandraの読み込みの弱点は弱まってくる(b-tree形式の巨大なインデックスのシークに比べて)

詳細はMemtableSSTableをご覧ください.

各ノード間でジョインしたとログが残っているのにnodetool ringは何故1つのエントリしか見えないのでしょうか?

この現象は各ノードに同じトークンを割り当てたときに起こります.基本的にそのようなことはしないでください.

この現象はCassandraを仮想マシン(Debianパッケージ,自動的にCassandraインストール後に起動,トークンの生成と保存を行う)を使って,そのVMをコピーした場合に発生します.

もっとも簡単な対処方法はデータとコミットログをクリアすると,各ノードは次のリスタート時にランダムなトークンを生成します.

レンジスキャンで削除したはずのキーが残っているのは何でですか?

Because get_range_slice says, "apply this predicate to the range of rows given," meaning, if the predicate result is empty, we have to include an empty result for that row key. It is perfectly valid to perform such a query returning empty column lists for some or all keys, even if no deletions have been performed.

So to special case leaving out result entries for deletions, we would have to check the entire rest of the row to make sure there is no undeleted data anywhere else either (in which case leaving the key out would be an error).

This is what we used to do with the old get_key_range method, but the performance hit turned out to be unacceptable.

See DistributedDeletes for more on how deletes work in Cassandra.

動いているCassandra上でReplicationFactorを変更することは出来ますか?

可能ですが、既存データのレプリカの数を変更するために、リスタートと手動リペアが必要です。

  • クラスターのすべてのノードにおいて、ストレージ設定内の対象キースペースのReplicationFactorを更新します。
  • クラスターのすべてのノードをリスタートします。

ReplicationFactorを減らす場合:

  • 余剰のレプリカデータを削除するため、"nodetool cleanup" を各ノードに対して実施します。

ReplicationFactorを増す場合:

  • Anti-Entropyによるリペアを実施するため、"nodetool repair"を各ノードで実行します。これは重い処理ですので、クラスターの性能に悪影響があるかもしれません。リペアはノード別に順番に実施することを強く推奨します。全ノードで同時にリペアを実行するとひどく時間がかかるか、あるいはクラッシュするかもしれません。

Cassandraで巨大なファイルやBLOBを保存できますか?

現在のCassandraは巨大なファイルやBlobストレージとしては最適化されていません。しかし64MB前後のファイルまでであれば分割することなく容易に格納できます。これは主にCassandraが公式APIとして使用しているThriftに起因する制約事項です。Thriftではストリーミング機能が提供されていないため、write/readされるデータはメモリに収まらなければなりません。havior. Cassandraが将来Thrift以外のインターフェースをサポートすればこの問題を解決するかもしれませんが、今のところThrift自体の挙動を変更する計画はありません。Blobを格納するようなアプリケーションを設計する場合、以下のCassandraの特性にも注意して下さい。

  • 特定のキーとカラムに含まれるデータは単一ノードのディスクに収まらなければなりません。これがカラムやスーパーカラムの大きさに関する主要な制限になります。キーはレプリカ先のノードを決定するために使用されるため、特定のキーにひもづけられたデータは格納先ノードのストレージサイズによって規定されます。これはCassandraの分散モデルから派生する制限事項です。
  • 巨大なカラムを作成したり、読み出したりする場合、カラムのデータはRAMに読み込まれます。このようなケースでは容易にリソース集約的になりがちです。例えばそれぞれ10MBの画像ファイルを格納したカラムを含む行を200行RAMにロードすると小計2GBのRAMを使用することになります。ロードする行数が増えれば増えるほど、RAMの消費は急激に増加します。これを回避することは可能ですが、多くのアプリケーションで有効な解決方法を見いだすには事前の設計と試験が必要です。この挙動に関する情報についてはmemtablesを参照して下さい。また0.7で使用可能な対策については次のリンクを参照してください。 CASSANDRA-16
  • 更なる情報についてはCassandra Limitationsを参照して下さい。

Nodetoolをどのリモートホストに実行しても"Connection refused to host: 127.0.1.1"と言われます.何が起きているのでしょうか?

NodetoolはJMXに依存しています。JMXはRMIに依存しており、独自のリスナとコネクタをデータ交換の必要に応じて生成します。通常はこれらはバックグラウンドで透過的に動作しますが、接続元、あるいは接続先のホスト名の名前解決が正しく行われないと、混乱させられるような例外が発生する場合があります。

もしDNSを使用していないのであれば、接続元・接続先双方のホストが正しく{{/etc/hosts}}に登録されていることを確認してください。それでもうまくいかない場合は、JVMの起動時に{{-Djava.rmi.server.hostname=$IP}}を指定して下さい。ここで、$IPは他のホストからそのホストに接続できるIPアドレスです。

カラムファミリのすべての行を逐次処理対象にするにはどうしたらいいでしょうか?

簡単だが遅い方法: get_range_slicesを使います。空文字列から始め、呼び出し毎に最後に読んだキーを次の繰り返しのスタートキーに使います。

より良い方法: HadoopSupportを使います。

Keyspaceがstorage-conf.xmlに一つも定義されていないのはなぜでしょうか?

0.7以前ではcassandraはstorage-conf.xmlに静的に定義されたキースペースをロードしました。
CASSANDRA-44 によって稼働中のクラスタのスキーマを動的に変更する機能が追加されました。
このため、storage-conf.xmlに定義されたスキーマは無視するように動作を変更する必要がありました。同時に、0.7では設定ファイルはYAML形式に変更されました。
使用中のstoreage-conf.xmlがある場合、はじめに{{bin/config-converter}}ツールでYAML形式に変換する必要があります。このツールはstorage-conf.xmlからcassandra.yamlを生成します。cassandra.yamlを作成したら、定義されているスキーマを一度だけロードすることができます。
0.7では{{StorageServiceMBean}}に{{loadSchemaFromYAML}}メソッドが追加されています(JMXによってトリガされます。詳しくはhttps://issues.apache.org/jira/browse/CASSANDRA-1001を参照して下さい。)。このメソッドによりcassandra.yamlに定義されたスキーマをロードすることができますが、これは一度のみ実行可能な操作です。

{{loadSchemaFromYAML}}によってスキーマ定義されたノードは、以降のリスタートではsystemテーブルからスキーマを読み込みます。即ち、これ以降のスキーマ変更はthriftの{{system_*}}操作で行う必要があります。(API参照)

スキーマ変更は同一のノードで実行し、他のクラスターノードへのスキーマ変更の伝搬はcassandraに任せることをお勧めします。同じスキーマ変更を複数のノードで同時に実行した場合、マイグレーションの不整合を引き起こし、クラスターを混乱させる可能性があります。

詳細はLiveSchemaUpdatesを参照して下さい。

Cassandra用のGUI管理ツールはありませんか?

GTK製のデータブラウザ chiton が一番近いものです.
他のJava UIとしてhttp://code.google.com/p/cassandra-guiがあります。これはSwingベースのデータブラウザです。

挿入操作でInvalidRequestExeptionが発生し,次のようなメッセージが出力されます:"A long is exactly 8 bytes"

あなたは恐らくカラムファミリーの中でLongTypeカラムソーターを使っているはずです。LongTypeはカラムに格納される数値がぴったり64bit(8 byte)であり、またbig endianであることを想定しています。以下のサンプルコードで、phpからcassandraにintegerをpackして格納する方法、そしてcassandraから読み出してunpackする方法について説明します。

        /**
         * Takes php integer and packs it to 64bit (8 bytes) long big endian binary representation.
         * @param  $x integer
         * @return string eight bytes long binary repersentation of the integer in big endian order.
         */
        public static function pack_longtype($x) {
                return pack('C8', ($x >> 56) & 0xff, ($x >> 48) & 0xff, ($x >> 40) & 0xff, ($x >> 32) & 0xff,
                                ($x >> 24) & 0xff, ($x >> 16) & 0xff, ($x >> 8) & 0xff, $x & 0xff);
        }

        /**
         * Takes eight bytes long big endian binary representation of an integer and unpacks it to a php integer.
         * @param  $x
         * @return php integer
         */
        public static function unpack_longtype($x) {
                $a = unpack('C8', $x);
                return ($a[1] << 56) + ($a[2] << 48) + ($a[3] << 40) + ($a[4] << 32) + ($a[5] << 24) + ($a[6] << 16) + ($a[7] << 8) + $a[8];
        }

Cassandraから"ClusterName mismatch: oldClusterName != newClusterName"が出力され,起動できません

オペレーターによる誤操作を避けるため、Cassandraはクラスター名をsystemテーブルに記録しています。何からの理由でクラスター名を変更する必要がある場合に、ノードのトークンを設定ファイルで指定している場合、あるいはノードのトークンが変更されても構わない場合には、クラスター名を変更する前にすべてのカラムファミリーを強制的にcompactionしてからsystem/LocationInfo* を削除したほうが安全です。

batch_mutateはアトミックな操作ですか?

特殊な例として、単一のキーに対するbatch_mutationを考えると、それぞれのmutationはアトミックですが、アイソレーションはされていません。このようなmutationの最中にreadを行うと、部分的に更新された状態が見える可能性があります。
一般的に言うと、batch_mutateはアトミックではありません。ネットワークのラウンドトリップコストを削減するため、
batch_mutate
は複数のキーに対する操作を単一の呼び出しにまとめることを許しています。{{batch_mutate}}がmutationの途中で失敗した場合、既に適用されたmutationはそのまま残ります。ロールバックはされません。
このような場合、一般的にはクライアントアプリケーションは{{batch_mutate}}をリトライする必要があります。

Hadoop (例. Map/Reduce, Pig, Hive) はサポートされていますか?

Hadoop-Cassandra統合の最新情報については, HadoopSupport をご覧ください.

Cassandraクラスタはマルチテナント運用可能ですか?

スケジューリングや認証など、マルチテナント機能をより充実するための取り組みが行われています。詳しくはMultiTenantを参照して下さい。

どんなユーザが何のためにCassandraを使っているのでしょうか?

Cassandraを使用しているユーザや、その用途についてはCassandraUsersを参照して下さい。

Cassandra用のODBCドライバはありませんか?

ありません。

Cassandraに直接ログを記録する方法はありますか?

Cassandraに直接ログする方法についてはLoggingToCassandraを参照して下さい。

RedHat Enterprise Linuxを使う上で何か問題はありますか?

もしselinuxがONになっていたら、OFFにしてください。

認証・権限付与の機能はありますか?

あります。詳細についてはExtensibleAuthを参照して下さい。

データをバルクロードするにはどうしたらいいでしょうか?

BulkLoadingを参照して下さい。

レンジスライスやシーケンシャルスキャンはなぜ期待通りの結果を返さないのでしょうか?

あなたは多分RandomPartitionerを使っているはずです。これはデフォルト設定で、データが特定のノードに偏ることを避けられます。一方で、RandomPartitionerを使った場合、行はあなたが指定するrow keyの字句的順序ではなく、 row keyのmd5ハッシュ値の順で並びます。

ページングが目的なら、start keyとend keyを空に指定し、row count引数を指定すれば実現できます。次のページを取得するには前のページで取得した最後のキーをstart keyに指定します。
行の中であれば、カラムをカラム名の順序で取得できます。データを各行に配置する方法を工夫することで、行そのものが整列していなくても済む場合もあるでしょう。

メーリングリストの配信を停止するにはどうしたらいいですか?

user-unsubscribe@cassandra.apache.orgにメールを送ってください。

Compactionを実行してもディスク使用量が減らないのはなぜでしょうか?

compactionによって不要になったSSTableはJVMがGCを実行する際に非同期的に削除されます。必要ならjconsoleで強制的にGCさせることもできますが、Cassandraは空きスペースが少なくなれば自動的にGCを実行します。
不要になったsstableにはcompactionマーカーが付与されます。GCが実行される前にサーバーがリスタートした場合、起動時にこれらのsstableを削除します。
詳細についてはMemtableSSTableを参照してください。

topコマンドの出力で,CassandraがJava heapの最大値よりも大きなメモリを使用しているのはなぜでしょうか?

Cassandraはzero-copy readのためにmmapを使用しています。即ち、sstableデータファイルをCassandraプロセスのアドレス空間にマップするためにOSの仮想メモリシステムを使用しているのです。これが仮想メモリが多量に使用されているように見える理由です。実際に使用されているのは仮想アドレス空間ですが、topなどのツールでは仮想メモリの消費としてレポートされます。64ビット環境ではアドレス空間はほぼ無限大ですので、あまり気にする必要はありません。通常の意味でのメモリ使用量の観点から問題となるのはbrk()でアロケートされたデータの量やmmapされた/dev/zeroです。これは使用された実メモリ量を示しています。
mmapされたファイルについて注意すべき点は、それらを物理メモリに保持する必要がないということです。つまり物理メモリに保持されたmmapファイルは基本的にはキャッシュとみなせます。これはちょうど通常のI/Oによってread/writeしたデータがカーネルのページキャッシュに保持されるのと同じです。
通常のI/Oとmmap()の違いは、mmap()がメモリをプロセスにマップするため、topでレポートされる仮想メモリサイズに影響することにあります。
通常のI/Oに替えてmmap()を使う主な利点は、メモリにアクセスするだけでreadが完了する点にあります。そのメモリ領域が実際にロードされている(residentである)場合は、正にそれを読むだけで、ページフォルトも不要です。(カーネル空間に入ったり、コンテキストスイッチするオーバーヘッドも必要ありません)
詳細については次のリンクを参照してください。http://www.varnish-cache.org/trac/wiki/ArchitectNotes

Keyspaceを更新したり、スナップショットをとろうとしたときに java.io.IOException: Cannot run program "ln" が発生します。

Keyspaceを更新する場合、最初にスナップショットが取られます。これには既存のSSTableへのハードリンクを生成することを意味しますが、Javaにはハードリンクをネイティブで生成する機能がないため、"ln"をfork/execする必要があります。forkを実行する際には、例え子プロセスがそのすべてを使用しないとしても親プロセスと同じ大きさのフリーメモリが必要です。Javaは巨大なプロセスですので、これは難しい問題です。解決策はJava Native Accessをインストールし、ハードリンクの生成をネイティブで実行することです。

Cassandraはどのデータがどのノードに配置されているかをどのように判定しますか?

The set of nodes (a single node, or several) responsible for any given piece of data is determined by:
特定のデータを担当するノードセット(単一、または複数のノードの場合があります)は以下の要素で決定されます。

  • 行キー(データは行キーでパーティションされます)
  • レプリケーションファクター(どれだけのノードが指定された行のレプリカを持つか決定します)
  • レプリケーションストラテジー(_どの_ノードがレプリカセットとなるかを決定します)

SimpleStrategyの場合、レプリカはリング上の後続ノードに配置されます。即ち最初のノードはパーティショナーと行キーによって決定され、残りのレプリカデータは後続ノード上に配置されることになります。NetworkTopologyStrategyの場合、レプリカ配置はデータセンターとラック構成によって影響されます。異なるラックやデータセンターに配置されたノードがどのようにリング上に配置されるかにも依存します。

注意すべきなのは、Cassandraは現在の負荷や、ノードの死活情報、クライアントが接続したノード等よってレプリカセットの構成を変更しないと言うことです。

JMXで行キャッシュあるいはキーキャッシュのヒット率が0.XX123456789のように表示されます。これはXX%という意味でしょうか?それとも0.XX%でしょうか?

XX%です。

Commit Logが大変肥大化しています。Cassandraは古いCommit Logを削除しないのでしょうか?

少数のカラムファミリーを非常に低いスループットで使用していませんか?このようなカラムファミリはフラッシュされる頻度が低く、commit logは削除されません。回避方法をひとつ紹介します。それは、カラムファミリー別のオプションである、memtable_flush_after_minを設定することです。この設定により、カラムファミリーを X 分毎にフラッシュさせることができます。初期設定としては、60分からはじめるのがよいでしょう。この設定をするには、cassandra-cliで以下のコマンドを実行して下さい。

update column family XXX with memtable_flush_after=60;

seedとは何ですか?

Ring内のノードがある特定のノードをseedとして参照するように設定すると、それらのノードはseedノードに対してより頻繁にGossipメッセージを送信します(詳しくはArchitectureGossipを参照して下さい )。言い換えると、seedはGossipネットワークのハブとして機能します。Seedノードが存在することにより、リング内の各ノードは他のノードの状態変化をよりすばやく検出することができるようになります。

新規のノードをリングに追加する場合にもSeedが使用されます。新規ノードはseedを参照してリング内の他のノードの情報を学習します。リングにノードを追加する場合、少なくとも一つの稼働中のseedを指定しなければなりません。一度リングにjoinして他のノード情報を学習すれば、以降はseed無しでもboot可能です。

seedとして設定したノードはauto_bootstrapしません。もし新規のノードをseedとして追加したいなら、まずauto_bootstrapでリングにjoinし、次にseedとして設定する必要があります。

seedが1台しかない場合、それは単一障害点になりますか?

カラムファミリーがレプリケートされているのであれば、リングにseedが1台しかなくても単一障害点とはなりません。seedが稼働していなくてもリングはブート可能ですし、要求を処理できます。しかしseedが無い場合、リング内のノード状態の変化の検出に時間がかかるようになります。本番環境では複数のseedを配置した方がよいでしょう。

jconsoleでXという操作が実行できないのはなぜでしょうか? (例 getNaturalEndpoints)

JMXインターフェースの幾つかの操作はjconsole上ではボタンが無効となっていて、呼び出すことができません。 jconsoleは配列引数を持つ操作の実行をサポートしていないため、このような操作をjconsoleから実行することはできません。配列引数を持つJMX操作を実行するには、独自のJMXクライアントを作成するか、あるいは配列引数をサポートしているJMX管理ツールを使用する必要があります。

キーには最大どのくらいのサイズのデータが使用可能でしょうか?

キー(及びカラム名)は64Kバイト以下でなければなりません。

リング内のルーティング性能はキーのサイズに対してO(N)のオーダーであり、更新はO(N log N)です。一般的にはこれらの影響は他の要素に比べて無視できる範囲ですが、非常に大きい「生の」キーを扱う事例では代わりにそれらのハッシュ値をキーとして使用しているユーザもいます。

https://c.statcounter.com/9397521/0/fe557aad/1/|stats

  • No labels