よくある質問
listen_address
を0.0.0.0(すべてのアドレス)でリスンするように設定できないのはなぜですか?
Cassandraはゴシップベースの分散システムであり、listen_address
はノードが他のノードに到達するために伝えるアドレスです。「私のどのアドレスでも連絡してください」と他のノードに伝えるのは悪い考えです。クラスタ内の異なるノードがあなたのために異なるアドレスを選択すると、問題が発生します。
クラスタ内の各ノードのlisten_address
にIPを手動で指定したくない場合(理解できます!)、空欄のままにしておくと、CassandraはInetAddress.getLocalHost()
を使用してアドレスを選択します。その後、あなたまたは運用チームが正しく解決できるようにする必要があります(/etc/hosts/
、DNSなど)。
このプロセスの例外はJMXであり、デフォルトでは0.0.0.0にバインドされます(Javaバグ6425769)。
より詳細な情報は256
と43
を参照してください。
Cassandraは何ポートを使用しますか?
デフォルトでは、Cassandraはクラスタ通信に7000(SSLが有効な場合は7001)、ネイティブプロトコルクライアントに9042、JMXに7199を使用します。ノード間通信ポートとネイティブプロトコルポートはcassandra.yaml
で設定できます。JMXポートはcassandra-env.sh
(JVMオプションを使用)で設定できます。すべてのポートはTCPです。
新しいノードを追加すると、クラスタ内の既存のデータはどうなりますか?
新しいノードがクラスタに参加すると、クラスタ内の他のノードに自動的に接続し、適切なデータを自身にコピーします。トポロジの変更
を参照してください。
Cassandraからデータ削除しても、ディスク使用量は変わりません。何が原因ですか?
Cassandraに書き込んだデータはSSTableに永続化されます。SSTableは不変であるため、削除を実行してもデータは実際には削除されません。代わりに、値の新しいステータスを示すマーカー(「墓石」とも呼ばれます)が書き込まれます。しかし心配しないでください。データと墓石の間で発生する最初の圧縮時に、データは完全に削除され、対応するディスク領域が回復されます。詳細については、圧縮
を参照してください。
ノードが互いにリングに参加していることをログに記録しているにもかかわらず、nodetool ringに1つのエントリしか表示されないのはなぜですか?
これは、各ノードに同じトークンが割り当てられている場合に発生します。それをしてはいけません。
これは、CassandraをVMにインストールしてデプロイする場合(特に、インストール後にCassandraを自動的に起動するDebianパッケージを使用する場合、トークンが生成されて保存されるため)、そのVMを他のノードに複製する場合によく発生します。
最も簡単な修正方法は、データとcommitlogディレクトリをワイプすることです。これにより、各ノードが次回の再起動時にランダムなトークンを生成します。
ライブクラスタでレプリケーションファクター(キースペース)を変更できますか?
はい、ただし、既存のデータのレプリカ数を変更するには、完全な修復(またはクリーンアップ)を実行する必要があります。
-
目的のキースペースのレプリケーションファクターを
Alter <alter-keyspace-statement>
します(たとえば、cqlshを使用)。 -
レプリケーションファクターを削減する場合は、クラスタで
nodetool cleanup
を実行して、余分なレプリケートされたデータを削除します。クリーンアップはノードごとに実行されます。 -
レプリケーションファクターを増やす場合は、
nodetool repair -full
を実行して、データが新しい設定に従ってレプリケートされるようにします。修復はレプリカセットごとに実行されます。これは集中的なプロセスであり、クラスタのパフォーマンスに悪影響を与える可能性があります。一度にクラスタ全体を修復しようとすると、クラスタが圧倒される可能性が高いため、ローリング修復を行うことを強くお勧めします。すでに修復されたSSTableがスキップされないようにするには、完全な修復(-full
)を実行する必要があることに注意してください。実際にはデータを持つレプリカが参照されるように、ConsistencyLevel.QUORUM
またはALL
(既存のレプリケーションファクターに応じて)を使用する必要があります。それ以外の場合は、修復が完了するまでデータが存在しないとクライアントに伝えられる可能性があります。
Cassandraに(大規模な)BLOBを保存できますか?
Cassandraは大規模なファイルまたはBLOBストレージには最適化されておらず、単一のblob
値は常に完全に読み取られてクライアントに送信されます。そのため、小さなblob(1桁MB未満)の保存は問題ありませんが、大きなblobを手動で小さなチャンクに分割することをお勧めします。
特に、デフォルトでは、cassandra.yaml
ファイルのmax_mutation_size
設定(デフォルトでcommitlog_segment_size
の半分、つまり32MiB)のために、16MiBを超える値はCassandraによって拒否されます。
Nodetoolは、リモートホストに対して「ホストへの接続が拒否されました: 127.0.1.1」と表示されます。何が原因ですか?
NodetoolはJMXに依存し、JMXはRMIに依存し、RMIは交換の両端で独自のリスナーとコネクタを必要に応じて設定します。通常、これらはすべて舞台裏で透過的に発生しますが、接続するホストまたは接続されるホストの不正な名前解決により、クロスワイヤと混乱を招く例外が発生する可能性があります。
DNSを使用していない場合は、両端の/etc/hosts
ファイルが正確であることを確認してください。それでも失敗する場合は、cassandra-env.sh
の一番下付近で-Djava.rmi.server.hostname=<公開名>
JVMオプションを、リモートマシンからアクセスできるインターフェースに設定してみてください。
操作をバッチ処理すると、バルク読み込みの速度が上がりますか?
いいえ。データの読み込みにバッチを使用すると、一般的にレイテンシの「スパイク」が追加されるだけです。代わりに非同期INSERTを使用するか、真のバルク読み込み
を使用してください。
例外は、単一パーティションへの更新のバッチ処理であり、良いことです(単一バッチのサイズが妥当な範囲内である限り)。しかし、決して盲目的にすべてをバッチ処理しないでください!
RHELノードがリングに参加できません
SELinuxが有効になっているかどうかを確認します。有効になっている場合は、無効にします。
topで、CassandraがJavaヒープ最大値よりもはるかに多くのメモリを使用していると報告されるのはなぜですか?
Cassandraは内部的にメモリマップドファイル(mmap)を使用します。つまり、オペレーティングシステムの仮想メモリシステムを使用して、多くのオンディスクファイルをCassandraプロセスのアドレス空間にマップします。これにより、仮想メモリ(つまり、アドレス空間)が「使用」され、topなどのツールで報告されますが、64ビットシステムでは仮想アドレス空間は事実上無制限であるため、心配する必要はありません。
通常の意味での「メモリ使用量」の観点から重要なのは、brk()またはmmap’d /dev/zeroで割り当てられたデータ量であり、これは実際に使用されているメモリを表します。重要な問題は、mmap’dファイルの場合、物理メモリに常駐するデータを保持する必要がないことです。したがって、物理メモリに常駐させるものは、通常のI/Oがカーネルページキャッシュに読み書きするデータを保持させるのと同じように、基本的にキャッシュとして存在するだけです。
通常のI/Oとmmap()の違いは、mmap()の場合、メモリが実際にプロセスにマップされるため、topコマンドで報告される仮想サイズに影響を与えることです。mmap()を標準I/Oの代わりに使用する主な理由は、読み込みがメモリへのアクセスだけで済むという事実です。メモリが常駐している場合、読み込みはメモリへのアクセスだけで済み、ページフォルトさえ発生しません(したがって、カーネルへの進入やセミコンテキストスイッチによるオーバーヘッドはありません)。詳細はこちらを参照してください。
シードとは何か?
シードは、クラスタの検出に起動時に使用されます。
ノードをシードとして参照するように設定すると、リング内のノードは、非シードノードよりもシードノードにゴシップメッセージを送信する頻度が高くなります(ゴシップに関するセクション <gossip>
も参照)。言い換えれば、シードはゴシップネットワークのハブとして機能します。シードを使用することで、各ノードは他のノードのステータス変更を迅速に検出できます。
シードは、新しいノードがブートストラップ時にリング内の他のノードを学習するためにも参照されます。新しいノードをリングに追加する際は、少なくとも1つの稼働中のシードノードを指定して接続する必要があります。ノードがリングに参加すると、他のノードに関する情報を学習するため、以降の起動ではシードは必要ありません。
いつでもノードをシードにすることができます。シードノードには特別なものは何もありません。シードリストにノードをリストアップすれば、それはシードになります。
シードは自動ブートストラップを行いません(つまり、ノードが自身のシードリストに自身を含んでいても、自動的に自身にデータを転送しません)。ノードにそのような動作をさせたい場合は、最初にブートストラップしてから、後でシードに追加してください。データがない(新規インストール)場合は、ブートストラップをまったく心配する必要はありません。
シードの推奨使用方法
-
データセンターごとに2つ(またはそれ以上)のノードをシードノードとして選択します。
-
シードリストをすべてのノードに同期します。
なぜjconsoleでJMXメソッドXを呼び出せないのか?
一部のJMX操作は配列引数を使用しており、jconsoleは配列引数をサポートしていないため、jconsoleではこれらの操作を呼び出すことができません(ボタンは無効になっています)。このような操作を呼び出すには、JMXクライアントを作成するか、配列対応のJMX監視ツールを使用する必要があります。
ログに「…メッセージが破棄されました…」と表示されるのはなぜですか?
これは、ロードシェディング(Cassandraが処理できる以上のリクエストに対して防御している状態)の症状です。
ノードが受信したノード間メッセージが、適切なタイムアウト内(cassandra-yaml
内のread_request_timeout
、write_request_timeout
など)に処理されない場合、(コーディネータノードが応答を待たなくなるため)処理される代わりに破棄されます。
書き込みの場合、これは変更が送信されたすべてのレプリカに適用されなかったことを意味します。この不整合は、リードレペア、ヒント、または手動レペアによって修復されます。書き込み操作はタイムアウトしている可能性もあります。
読み込みの場合、これは読み込みリクエストが完了しなかった可能性があることを意味します。
ロードシェディングはCassandraアーキテクチャの一部です。これが永続的な問題である場合、一般的にノードまたはクラスタの過負荷を示しています。
Cassandraがjava.lang.OutOfMemoryError: Map failed
でクラッシュする
Cassandraが「Map failed」メッセージで**特に**クラッシュしている場合、それはOSがJavaによるメモリのロックを拒否していることを意味します。Linuxでは、これは通常、memlockが制限されていることを意味します。/proc/<cassandraのプロセスID>/limits
でこれを確認し、(例えば、bashでulimitを使用して)値を上げます。vm.max_map_count
を増やす必要がある場合もあります。Debianパッケージはこれを自動的に処理します。
同じタイムスタンプで2つの更新が行われた場合、どうなるか?
異なるレプリカで異なる順序で到着する可能性があるため、更新は可換である必要があります。Cassandraが(タイムスタンプが一致した場合に)勝者を決定する決定論的な方法を持っている限り、選択されたものは他のものと同じように有効であり、その詳細は実装の詳細として扱う必要があります。つまり、タイムスタンプが一致する場合、Cassandraは2つのルールに従います。まず、削除は挿入/更新よりも優先されます。次に、2つの更新がある場合、辞書順で値が大きい方が選択されます。
新しいノードのブートストラップが「ストリーム失敗」エラーで失敗するのはなぜですか?
2つの主な可能性があります。
-
GCが長いポーズを作成し、ストリーミングプロセスを中断している可能性があります。
-
バックグラウンドで実行されているコンパクションが、ストリーミングを十分に長く保持してTCP接続が失敗している可能性があります。
最初のケースでは、通常のGCチューニングのアドバイスが適用されます。2番目のケースでは、TCP keepaliveをより低い値に設定する必要があります(Linuxではデフォルト値が非常に高くなっています)。次のコマンドを実行してみてください。
$ sudo /sbin/sysctl -w net.ipv4.tcp_keepalive_time=60 net.ipv4.tcp_keepalive_intvl=60 net.ipv4.tcp_keepalive_probes=5
これらの設定を永続的にするには、/etc/sysctl.conf
ファイルに追加します。
注:GCEのファイアウォールは、10分以上非アクティブなTCP接続を常に中断します。この環境では、上記コマンドの実行を強くお勧めします。