我可以看到使用datastax cassandra驱动程序(3.0)的奇怪行为。我已经创建了一个新集群,然后我使用相同的集群对象启动了一组线程。如果我将线程保持为1或2,我看到平均提取时间为5毫秒,但如果我将线程增加到60,则提取时间增加到200毫秒(每个线程)。奇怪的是,如果我让60个线程应用程序运行并且我在同一台机器上启动另一个只有1个线程的进程,那个单线程应用程序的提取时间再次为5ms。所以它似乎与客户有关。我多次重复相同的测试以避免缓存冷启动问题。 以下是集群对象的配置方式:
PoolingOptions poolingOptions = new PoolingOptions();
poolingOptions
.setConnectionsPerHost(HostDistance.LOCAL, parallelism, parallelism+20)
.setConnectionsPerHost(HostDistance.REMOTE, parallelism, parallelism+20)
.setMaxRequestsPerConnection(HostDistance.LOCAL, 32768)
.setMaxRequestsPerConnection(HostDistance.REMOTE, 2000);
this.cluster = Cluster.builder()
.addContactPoints(nodes)
.withRetryPolicy(DowngradingConsistencyRetryPolicy.INSTANCE)
.withReconnectionPolicy(new ConstantReconnectionPolicy(100L))
.withLoadBalancingPolicy(new TokenAwarePolicy(DCAwareRoundRobinPolicy.builder().build()))
.withCompression(Compression.LZ4)
.withPoolingOptions(poolingOptions)
.withProtocolVersion(ProtocolVersion.V4)
.build();
有没有人遇到过同样的问题?这似乎是一个客户端配置问题。对Netty可能还有一些额外缺失的配置?
更新1 应用程序正在做的是使用如下查询提取数据块:
select * from table where id=? and ts>=? and ts<?
所以我有60个线程并行提取这些数据。 id是分区键。每个查询都由线程执行:
//Prepare statement
PreparedStatement stmt = ... get the prepared statment cached
BoundStatement bstmt = stmt.bind(...)
//Execute query
long te1 = System.nanoTime();
ResultSet rs = this.session.execute(bstmt);
long te2 = System.nanoTime();
//Fetch...
Iterator<Row> iterator = rs.iterator();
while (!rs.isExhausted() && iterator.hasNext()) { .... }
会话是一个并且共享所有线程。我测量的是session.execute()方法调用的平均时间。
谢谢!
更新2 这是架构定义
CREATE TABLE d_t (
id bigint,
xid bigint,
ts timestamp,
avg double,
ce double,
cg double,
p double,
w double,
c double,
sum double,
last double,
max double,
min double,
p75 double,
p90 double,
p95 double,
squad double,
sumq double,
wavg double,
weight double,
PRIMARY KEY ((id), xid, ts)
) WITH CLUSTERING ORDER BY (xid DESC, ts DESC)
and compaction = {'class': 'SizeTieredCompactionStrategy'}
and gc_grace_seconds=86400
and caching = { 'keys' : 'ALL', 'rows_per_partition':'36000' }
and min_index_interval = 2
and max_index_interval = 20;
更新3 也试过
.setMaxRequestsPerConnection(HostDistance.LOCAL, 1)
.setMaxRequestsPerConnection(HostDistance.REMOTE, 1)
没有变化
答案 0 :(得分:0)
最终我认为这取决于你的代码在做什么。你能分享一个例子吗?
关于延迟增加,您如何衡量?根据您的陈述:
60个并发请求实际上并不是太多,一般来说,您不需要使用datastax java驱动程序执行每个请求的线程。您可以使用单个应用程序线程实现高吞吐量,因为驱动程序使用的netty事件循环组将完成大部分工作。奇怪的是,如果我让60个线程应用程序运行并且我在同一台机器上启动另一个只有1个线程的进程,那个单线程应用程序的提取时间再次为5ms。
本机协议C *使用允许每个连接多个请求。正如您在此处配置的那样,每个连接最多可达32768个并发请求。实际上,您根本不需要触摸此配置,因为默认情况下(每个连接1000个请求)是明智的,因为在实践中C *不会从cassandra.yaml处理超过native_transport_max_threads
的情况。 (默认为128)并排队其余部分。
因此,每个主机不需要很多连接。每个主机的默认1个核心连接应该足以支持60个并发请求。增加每个主机的连接数对您来说不会有太大帮助,在分析中我发现每个主机有8个连接的收益递减,具有高吞吐量(数千个并发请求),并且每个主机通过16个连接后吞吐量变得更糟,虽然您的里程可能因环境而异。
尽管如此,我建议不要将PoolingOptions
配置为超出默认值,除了可能将核心和最大值设置为8,以用于尝试实现更高吞吐量(> 10k请求/秒)的情况。