我们使用 rest api 在 cassandra 中执行查询,其中一个获取计数的查询给我们带来了问题。
我们已经构建了Cassandra集群,最近,我们已经完成了备份和恢复,并将所有数据复制到新的集群。 我们已经在表上完成了节点工具刷新,并且还进行了节点工具修复。
但是,我们的某些 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的系统.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 调用给出正确的值。
如果需要任何其他详细信息,请告诉我。
不要使用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