ruby Simple INSERT偶尔会失败,出现Cassandra::Errors::TimeoutError、Cassandra::Errors::WriteTimeoutError

voj3qocg  于 12个月前  发布在  Ruby
关注(0)|答案(3)|浏览(148)

在具有3个节点的生产环境中,本地仲裁偶尔会发生插入失败,我们只得到Cassandra::Errors::TimeoutError而不是Cassandra::Errors::WriteTimeoutError,我认为这说明它无法连接到节点,但我没有得到Cassandra::Errors::NoHostsAvailable: All attempted hosts failed
我看了看cassandra的日志,什么都没有,应用程序日志显示错误
它每天发生1 k,通常从呼叫方重试结果成功.
我猜司机有问题

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'
j13ufse2

j13ufse21#

根据你的描述
它每天发生1k次,通常呼叫方重试会成功
cassandra集群的大小不适合你在其上的工作负载。
您可能必须根据集群上的负载适当地调整集群的大小或扩展集群。这是一个太广泛的主题,或者你可以简单地选择a Serverless SaaS offering like this,不必担心缩放,因为它会自动为你做。
有几个链接可以帮助你,

cwdobuhd

cwdobuhd2#

你提到的这些错误都是互不相同的,而且是相互排斥的。
TimeoutError是一个客户端错误,当驱动程序在:timeout秒内没有收到协调器(服务器端)的反馈时,它会引发此错误。这意味着司机放弃了等待协调员的回应。
WriteTimeoutError是协调器返回的服务器端错误,当副本没有确认write_request_timeout_in_ms(在cassandra.yaml中)内的写入请求时,通常是因为commitlog/磁盘无法跟上。
当驱动程序尝试联系的所有主机都不可用或无响应时,驱动程序将引发NoHostsAvailable错误。在这种情况下,驱动程序根本无法联系任何节点,因此协调器从未被选中来协调请求,这与上面的前两个错误完全不同。
如果您间歇性地看到TimeoutErrorWriteTimeoutError for INSERT语句,则很有可能在高峰应用程序流量期间引发错误,并指示您的群集无法科普负载。
这将是一个很好的时间来检查集群的容量,并限制应用程序流量或考虑通过添加更多节点来增加集群的容量。干杯!干杯!

nhjlsmyf

nhjlsmyf3#

所以我弄明白了问题所在,只是意识到我从来没有回答过这个问题。原因是大分区大小,cassandra日志出血的消息,如

WARN  [CompactionExecutor:170358] BigTableWriter.java:258 - Writing large partition xxx/yyy:1716208:2023-09-25-16-10 (103.262MiB) to sstable /data/cassandra/data/xxx/yyy-a88t665njhgs833sbjjkdl/nb-4343435-big-Data.db

每当刷新到memtable时,对于大于100 MB的分区,它会大大增加延迟。
解决方案-
这很简单,我们的分区键是some eother col + bucket(从我们的timeuuid类型的集群列中提取yyyy-mm-dd-hh-mm),我们从分钟中截取最后一位数字,所以本质上10分钟窗口内的任何内容都会进入单个分区,我将其更改为1分钟。在我们重新设计table的时候它止住了血

相关问题