【问题标题】:Receiving inconsistent counts from cassandra从 cassandra 收到不一致的计数
【发布时间】:2017-08-06 12:40:44
【问题描述】:

我们正在使用 rest api 在 cassandra 中执行查询,而我们获取计数的查询之一给我们带来了问题。

我们已经构建了 cassandra 集群,最近,我们完成了备份和恢复并将所有数据复制到新集群。 我们已经对表进行了 nodetool 刷新,并且也进行了 nodetool 修复。

但是,我们的一些 API 调用失败并返回不一致的结果。

1) 计数查询中有分区键。没有看到任何读取超时或任何来自 api 调用的错误。

2) 这就是我们创建会话的代码的样子。

val poolingOptions = new PoolingOptions
    poolingOptions
      .setCoreConnectionsPerHost(HostDistance.LOCAL, 4)
      .setMaxConnectionsPerHost(HostDistance.LOCAL, 10)
      .setCoreConnectionsPerHost(HostDistance.REMOTE, 4)
      .setMaxConnectionsPerHost( HostDistance.REMOTE, 10)

val builtCluster = clusterBuilder.withCredentials(username, password)
      .withPoolingOptions(poolingOptions)
      .build()
val cassandraSession = builtCluster.get.connect()
val preparedStatement = cassandraSession.prepare(statement).setConsistencyLevel(ConsistencyLevel.QUORUM)
cassandraSession.execute(preparedStatement.bind(args :_*))

集群配置:

6 台机器:3 个种子

cassandra 永远不会在任何机器上停机

我们使用的是 apache cassandra 3.9 版本

在 3.1.1 版本中使用 cassandra-driver-core 工件。

3) nodetoop tpstats 显示没有失败。

4) 从 cassandra 的 system.log 中看不到任何其他问题。我们只看到以下几个警告。

Maximum memory usage reached (512.000MiB), cannot allocate chunk of 1.000MiB
WARN  [ScheduledTasks:1] 2017-03-14 14:58:37,141 QueryProcessor.java:103 - 88 prepared statements discarded in the last minute because cache limit reached (32 MB)

第一个 api 调用返回 0,随后的 api 调用给出正确的值。

如果需要任何其他详细信息,请告诉我。

【问题讨论】:

  • 你的表结构是什么,你正在执行什么查询?
  • 我们有 4 列的表,其中之一是分区键,并且已选择几列(日期列 + 文本列)作为聚类键。我们的查询将如下所示。 SELECT count(*) FROM table_name WHERE parition_column=? AND text_column_of_clustering_key=? AND date_column_of_clustering_key=?
  • 你的复制策略/因素是什么?对该表的写入处于什么一致性级别?
  • 复制因子为3,写一致性为ONE,读一致性为QUORUM。

标签: cassandra datastax-java-driver


【解决方案1】:

不要使用count(*),使用计数器
count(*) 效率很低。 Cassandra 需要扫描所有行只是为了给你计数。如果您有大量数据,cassandra 可能会抛出超时异常。

改用计数器:

计数器是一个特殊的列,用于存储以增量方式更改的数字。例如,您可以使用计数器列来计算页面被查看的次数。

让我们定义一个表:

CREATE TABLE counter_test (
    pk int,
    ctkey text,
    cdkey date,
    count counter,
    PRIMARY KEY (pk, ctkey, cdkey)
);

增加计数器的值:

UPDATE counter_test SET count = count + 10 WHERE pk = 1 AND ctkey = 'hi' AND cdkey = '2017-03-16';

减少计数器的值:

UPDATE counter_test SET count = count - 5 WHERE pk = 1 AND ctkey = 'hi' AND cdkey = '2017-03-16';

选择计数器的值:

SELECT * FROM counter_test WHERE pk = 1 AND ctkey = 'hi' AND cdkey = '2017-03-16';

你会得到:

 pk | ctkey | cdkey      | count
----+-------+------------+-------
  1 |    hi | 2017-03-16 |     5

来源:https://docs.datastax.com/en/cql/3.1/cql/cql_using/use_counter_t.html

【讨论】:

  • 我认为计数器不适用于我们的场景。当我们更新转储数据时,数据量也非常高。每次更新计数器都会影响性能,并不能真正解决我们的问题。
猜你喜欢
  • 2011-10-22
  • 2022-09-19
  • 2023-03-02
  • 1970-01-01
  • 2012-08-24
  • 2021-01-28
  • 1970-01-01
  • 1970-01-01
  • 2016-03-07
相关资源
最近更新 更多