【问题标题】:Sporadically failing Cassandra queriesCassandra 查询偶尔失败
【发布时间】:2016-02-19 18:44:14
【问题描述】:

我们在持续运行更新 Cassandra 中的计数器的 Java 应用程序时遇到了问题。通过监视服务器的负载,我们看不到与负载的任何相关性。查询非常稳定,因为它们只更新 8 个不同表中的值。 Java 应用程序每分钟都会触发数千个查询(可能是 20k 甚至 50k 个查询),但每隔一段时间就会有一些查询失败。发生这种情况时,我们将它们与异常消息一起写入文件。这个消息总是 Cassandra timeout during write query at consistency ONE (1 replica were required but only 0 acknowledged the write)

我们进行了一些谷歌搜索和故障排除,并采取了一些措施:

  • 将 Java 应用程序中的重试策略更改为 DefaultRetryPolicy 而不是 FallthroughRetryPolicy,以使客户端在失败时重试查询。
  • 将 Cassandra 节点上的 write_request_timeout_in_ms 设置从标准值 2000 更改为 4000,然后更改为 10000

这些操作减少了失败查询的数量,但它们仍然会发生。从每小时执行的数百万个查询中,我们看到在 24 小时内大约有 2000 个失败的查询。所有这些都有上面列出的相同例外,并且它们发生在不同的时间。

当然,我们从日志中看到,当查询确实失败时,需要一段时间,因为它正在等待超时并执行重试。

一些事实:

  • 我们运行 Cassandra v2.2.5(最近从 v2.2.4 升级)
  • 我们有一个具有 6 个节点的地理感知 Cassandra 集群:3 个在欧洲,3 个在美国。
  • 触发查询的 Java 应用程序是唯一与 Cassandra 通信的客户端(目前)。
  • java 应用数量为 10:5 在欧洲,5 在美国。
  • 我们异步执行所有查询 (session.executeAsync(statement);),并通过添加成功和失败的回调来跟踪各个查询。
  • 复制因子为 2。
  • 复制因子为 2。
  • 我们运行 Oracle Java 1.7.0_76 Java(TM) SE Runtime Environment (build 1.7.0_76-b13) Java HotSpot(TM) 64-Bit Server VM (build 24.76-b04, mixed mode)
  • 6 个 Cassandra 节点在裸机上运行,​​具有以下规格:
    • 存储是 raid 5 中的一组 SSD。
    • 每个节点有 2 个(6 核)Intel Xeon E5-2620 CPU @ 2.00GHz(硬件线程总数为 24)。
    • RAM 大小为 128GB。

我们如何创建集群:

private Cluster createCluster() {
    return Cluster.builder()
            .addContactPoints(contactPoints)
            .withRetryPolicy(DefaultRetryPolicy.INSTANCE)
            .withLoadBalancingPolicy(getLoadBalancingPolicy())
            .withReconnectionPolicy(new ConstantReconnectionPolicy(reconnectInterval))
            .build();
}
private LoadBalancingPolicy getLoadBalancingPolicy() {
    return DCAwareRoundRobinPolicy.builder()
            .withUsedHostsPerRemoteDc(allowedRemoteDcHosts) // == 3 
            .build();
}

我们如何创建键空间:

CREATE KEYSPACE IF NOT EXISTS traffic WITH REPLICATION = { 'class': 'NetworkTopologyStrategy', 'AMS1': 2, 'WDC1': 2};

示例表(它们看起来都相似)

CREATE TABLE IF NOT EXISTS traffic.per_node (
    node text,
    request_time timestamp,
    bytes counter,
    ssl_bytes counter,
    hits counter,
    ssl_hits counter,
    PRIMARY KEY (edge, request_time)
) WITH CLUSTERING ORDER BY (request_time DESC)
    AND compaction = {'class': 'DateTieredCompactionStrategy'};

【问题讨论】:

    标签: java cassandra


    【解决方案1】:

    很多评论:

    1. 首先对于Cluster 配置,您应该指定本地 DC 名称
    2. 您应该使用 LOCAL_ONE 而不是 ONE 以获得一致性级别以增强数据局部性
    3. 请勿更改write_request_timeout_in_ms 值。您只是在掩盖问题,真正的问题不是超时设置
    4. 您的复制因子是多少?
    5. Every minute the java applications fires thousands of queries (can be 20k or even 50k queries)--> 假设 RF=1,简单的数学计算给我每个节点大约 300 次插入/秒。它不是那么大,但您的插入可能会受到硬件的限制。您的 CPU 配置(内核数量)和磁盘类型(旋转磁盘或 SSD)是什么?
    6. 您是否限制异步插入?例如。分批发射 N 次插入,然后稍等片刻让集群呼吸。请在此处查看我的回答以了解节流:What is the best way to get backpressure for Cassandra Writes?

    【讨论】:

    • 感谢您的回答! (1) 我们提供的服务器列表是本地节点列表。 According to the documentation 这实现了同样的效果。 (2) 我们更新了代码,谢谢。 (3) 同意。 (4) 复制因子为 2。为清楚起见,将其添加到事实中。 (5) Cassandra 数据存储在 raid5 中的 SSD 上。更新了事实。 (6) 我们不限制插入。会考虑这个。 -- 我们很想知道您建议的更改的效果!
    • RAID5 中的 SSD 组是由 6 个节点共享还是 每个 节点的配置?
    • 每个节点都有自己的 SSD。
    • 这很奇怪,通常使用 SSD 和 24 核,每个节点应该能够处理 1000+ 插入/秒。您是否使用 dstatiostat 等工具监控系统负载以查看瓶颈是什么?阅读这篇关于 C* 调优的博文:tobert.github.io/pages/als-cassandra-21-tuning-guide.html
    • 是的,我们一直在使用 iostat 监控节点的负载和 IO。他们只使用了一小部分容量,因为他们现在唯一运行的是 Cassandra。
    猜你喜欢
    • 1970-01-01
    • 2018-08-08
    • 2017-08-22
    • 1970-01-01
    • 2015-01-25
    • 1970-01-01
    • 2018-04-09
    • 1970-01-01
    • 2018-11-02
    相关资源
    最近更新 更多