Techioz Blog

単純な INSERT が Cassandra::Errors::TimeoutError、Cassandra::Errors::WriteTimeoutError で散発的に失敗する

概要

3 つのノードを持つ運用環境では、ローカル クォーラムで散発的に挿入が失敗し、Cassandra::Errors::WriteTimeoutError ではなく Cassandra::Errors::TimeoutError が表示されるだけです。これは、ノードに接続できないことを示していると思いますが、そうではありません。 Cassandra::Errors::NoHostsAvailable を取得できません: 試行したホストはすべて失敗しました

cassandra ログを見ても何もありませんが、アプリケーション ログにはエラーが表示されます

これは 1 日あたり 1,000 件ほど発生しており、通常は呼び出し側からの再試行で成功します。

ドライバーに問題があると思います

    ruby '~> 2.7'
    gem "cassandra-driver", "~> 3.2.5"
    consistency:           :local_quorum,

    load_balancing_policies = {
        dc_aware_round_robin: Cassandra::LoadBalancing::Policies::DCAwareRoundRobin.new(
            datacenter,
            cassandra_used_hosts_per_remote_dc
        ),
        round_robin: Cassandra::LoadBalancing::Policies::RoundRobin.new
    }
CASSANDRA_CONNECT_TIMEOUT_MS: '600'
CASSANDRA_CONSISTENCY: LOCAL_QUORUM
CASSANDRA_RECONNECT_INITIAL_INTERVAL_MS: '100'
CASSANDRA_RECONNECT_MAX_INTERVAL_MS: '3000'
CASSANDRA_RECONNECT_MAX_RETRIES: '5'
CASSANDRA_RETRIES: '5'
CASSANDRA_RETRY_MAX_MS: '3000'
CASSANDRA_RETRY_MIN_MS: '100'

そこで、lib/cassandra/future.rbを調べました。

# Returns future value or raises future error
    #
    # @note This method blocks until a future is resolved or a times out
    #
    # @param timeout [nil, Numeric] a maximum number of seconds to block
    #   current thread for while waiting for this future to resolve. Will
    #   wait indefinitely if passed `nil`.
    #
    # @raise [Errors::TimeoutError] raised when wait time exceeds the timeout
    # @raise [Exception] raises when the future has been resolved with an
    #   error. The original exception will be raised.
    #
    # @return [Object] the value that the future has been resolved with
    def get(timeout = nil)
      @signal.get(timeout)
    end
Cassandra::Errors::TimeoutError
Timed out

非アプリでクラッシュしました: cassandra/future.rb in get

cassandra/future.rb の get 行 402

cassandra/session.rb の 127 行目で実行

/srv/_versions/events/events-202304261636-9ba0b992cd-master/vendor/bundle/ruby/2.7.0/gems/cassandra-driver-3.2.5/lib/cassandra/future.rb:637:in 'get',
/srv/_versions/events/events-202304261636-9ba0b992cd-master/vendor/bundle/ruby/2.7.0/gems/cassandra-driver-3.2.5/lib/cassandra/future.rb:402:in 'get',
/srv/_versions/events/events-202304261636-9ba0b992cd-master/vendor/bundle/ruby/2.7.0/gems/cassandra-driver-3.2.5/lib/cassandra/session.rb:127:in 'execute'

解決策

あなたの説明に基づいて、

cassandra クラスターは、負荷をかけているワークロードに対して適切なサイズではありません。

クラスタの負荷に応じて、クラスタのサイズを適切に変更したりスケールアップしたりする必要がある場合があります。これはトピックの範囲が広すぎます。あるいは、このようなサーバーレス SaaS オファリングを選択するだけで、スケーリングは自動的に行われるため、心配する必要はありません。

これに役立つリンクがいくつかあります。