Cassandra跟踪和客户端延迟之间的差异

Yur*_*uro 5 java driver cql cassandra cqlsh

我们使用的是Cassandra 2.0.15,并且看到来自所有应用程序主机的定期(大约每3分钟)的巨大读取延迟(大于60秒)出现。我们会根据对的调用来衡量此延迟session.execute(stmt)。同时,Cassandra跟踪报告的持续时间小于1s。我们还循环地在这些峰值延迟时间内通过cqlsh从同一主机查询,而cqlsh总是在1秒内返回。在Java驱动程序级别上,有什么可以解释这种差异?

-编辑:回复评论-

Cassandra服务器JVM设置:-XX:+CMSClassUnloadingEnabled -XX:+UseThreadPriorities -XX:ThreadPriorityPolicy=42 -XX:+HeapDumpOnOutOfMemoryError -Xss256k -XX:StringTableSize=1000003 -Xms32G -Xmx32G -XX:+UseG1GC -Djava.net.preferIPv4Stack=true -Dcassandra.jmx.local.port=7199 -XX:+DisableExplicitGC

客户端GC可以忽略不计(如下)。客户端设置:-Xss256k -Xms4G -Xmx4G,Cassandra驱动程序版本为2.1.7.1

客户端GC可以忽略不计

客户端测量代码:

val selectServiceNames = session.prepare(QueryBuilder.select("service_name").from("service_names"))

override def run(): Unit = {
  val start = System.currentTimeMillis()
  try {
    val resultSet = session.execute(selectServiceNames.bind())
    val serviceNames = resultSet.all()
    val elapsed = System.currentTimeMillis() - start
    latency.add(elapsed) // emits metric to statsd
    if (elapsed > 10000) {
      log.info("Canary2 sensed high Cassandra latency: " + elapsed + "ms")
    }
  } catch {
    case e: Throwable =>
      log.error(e, "Canary2 select failed")
  } finally {
    Thread.sleep(100)
    schedule()
  }
}
Run Code Online (Sandbox Code Playgroud)

集群构造代码:

def createClusterBuilder(): Cluster.Builder = {
  val builder = Cluster.builder()
  val contactPoints = parseContactPoints()
  val defaultPort = findConnectPort(contactPoints)
  builder.addContactPointsWithPorts(contactPoints)
  builder.withPort(defaultPort) // This ends up config.protocolOptions.port
  if (cassandraUsername.isDefined && cassandraPassword.isDefined)
    builder.withCredentials(cassandraUsername(), cassandraPassword())
  builder.withRetryPolicy(ZipkinRetryPolicy.INSTANCE)
  builder.withLoadBalancingPolicy(new TokenAwarePolicy(new LatencyAwarePolicy.Builder(new RoundRobinPolicy()).build()))
}
Run Code Online (Sandbox Code Playgroud)

我无法解释的另一项观察。我在循环中运行了两个以相同方式(如上)执行同一查询的线程,唯一的区别是黄色线程在查询之间休眠100millisec,绿色线程在查询之间休眠60sec。绿色线程比黄色线程更容易遇到低延迟(不到1秒)。

在此处输入图片说明

Yur*_*uro 2

我跟踪问题到远程数据中心节点上的查询超时。该集群在两个 DC 中都有节点,但密钥空间仅在本地 DC 内复制,因此甚至考虑删除节点,这令人惊讶。我能够将延迟降低

  1. 从 ONE 更改为 LOCAL_ONE 一致性并且
  2. 从普通的循环负载均衡器更改为 DC 感知负载均衡器(也使用延迟感知和令牌感知)。

在我看来,这仍然像是 Java 驱动程序中的一个错误,当密钥空间在该数据中心中明显不存在时,它会尝试使用远程数据中心的节点作为协调节点。另外,即使这在某种程度上不可能实现,我也使用了延迟感知策略,该策略应该将远程 DC 节点排除在考虑范围之外。