编程语言
首页 > 编程语言> > java-奇怪的Cassandra ReadTimeoutExceptions,取决于正在查询的客户端

java-奇怪的Cassandra ReadTimeoutExceptions,取决于正在查询的客户端

作者:互联网

我有三个带有或多或少默认配置的Cassandra节点的集群.最重要的是,我有一个Web层,其中包含两个用于负载平衡的节点,两个Web节点始终在查询Cassandra.一段时间后,由于存储在Cassandra中的数据变得不平凡,因此只有一个Web节点开始针对特定查询获取ReadTimeoutException. Web节点在各个方面都是相同的.

查询非常简单(?是日期的占位符,通常在当前时刻之前几分钟):

SELECT * FROM table WHERE time > ? LIMIT 1 ALLOW FILTERING;

该表是使用以下查询创建的:

CREATE TABLE table (
    user_id varchar,
    article_id varchar,
    time timestamp,
    PRIMARY KEY (user_id, time));
CREATE INDEX articles_idx ON table(article_id);

超时时,客户端等待的时间超过10秒,这毫不奇怪,这是在cassandra.yaml中为大多数连接和读取配置的超时.

有几件事让我感到困惑:

>仅当其中一个Web节点执行查询时才超时-其中一个节点始终失败,其中一个节点始终成功.
>当我从cqlsh中运行查询时,该查询会立即返回(尽管从那里运行它时似乎只命中一个节点)
>发出了其他查询,这些查询耗时2-3分钟(比10s超时长很多),根本不会超时

我无法在Java中跟踪查询,因为它超时.在cqlsh中跟踪查询并没有提供太多的见解.我宁愿不更改Cassandra超时,因为这是生产系统,我想先用尽非侵入式选择. Cassandra节点都有很多堆,它们的堆还远远不够用,GC时间似乎很正常.

任何想法/方向将不胜感激,我完全没有想法. Cassandra版本是2.0.2,使用com.datastax.cassandra:cassandra-driver-core:2.0.2 Java客户端.

解决方法:

我注意到了几件事:

>在将时间用作集群键时,它并不能真正帮助您,因为您的查询不受分区键(user_id)的限制. Cassandra仅通过群集分区中的键来排序.因此,现在您的查询正在拉回满足WHERE子句的第一行,该行按user_id的哈希标记值排序.如果您确实有成千上万的行,那么我希望这个查询每次都能从相同的user_id(或相同的选择少数)中拉回数据.
>“尽管看起来好像它从我那里运行时只命中一个节点”实际上,您的查询在运行它们时应该只命中一个节点.在查询中引入网络流量会使其变慢.我认为cqlsh中的默认一致性为ONE.这就是Carlo的想法发挥作用的地方.
> article_id的基数是什么?请记住,二级索引在“中间路线”基数上效果最佳.高(唯一)和低(布尔)都是不好的.
> ALLOW FILTERING子句不应在(生产)应用程序端代码中使用.像以往一样如果此表中有5000万行,则ALLOW FILTERING首先将它们全部拉回,然后根据WHERE子句修剪结果集.

意见建议:

> Carlo可能会尝试尝试不同(较低)的一致性级别.尝试在应用程序中将一致性级别设置为ONE,看看是否有帮助.
>执行“允许过滤”查询,或执行二级索引查询.他们俩都很烂,但是绝对不能一起做.我不会使用.但是,如果必须选择,我希望二级索引查询比ALLOW FILTERING查询的吸取更少.
>为了按您所描述的规模充分解决此问题,我将数据复制到查询表中.看起来您正在关注组织对时间敏感的数据,并获取最新的数据.这样的查询表应该做到这一点:

创建表tablebydaybucket(
    user_id varchar,
    article_id varchar,
    时间时间戳,
    day_bucket varchar,
    主键(day_bucket,时间)
带聚类排序依据(时间DESC);

用您的数据填充该表,然后此查询将起作用:

SELECT * FROM tablebydaybucket 
WHERE day_bucket='20150519' AND time > '2015-05-19 15:38:49-0500' LIMIT 1;

这将按day_bucket对数据进行分区,并按时间对数据进行集群.这样,您将不需要ALLOW FILTERING或二级索引.同样,您的查询将确保仅命中一个节点,并且Cassandra将不必拉回所有行并事后应用WHERE子句.并且按DESCending顺序按时间进行聚类,可以帮助您最近的行更快地返回.

标签:cassandra,java,cassandra-2-0
来源: https://codeday.me/bug/20191120/2042900.html