【问题标题】:Discrepancy between Cassandra trace and client-side latencyCassandra 跟踪和客户端延迟之间的差异
【发布时间】:2015-12-15 21:11:09
【问题描述】:

我们正在使用 Cassandra 2.0.15,并且看到所有应用程序主机定期(大约每 3 分钟)出现巨大的读取延迟(>60 秒)。我们在调用session.execute(stmt) 时测量此延迟。同时,Cassandra 跟踪报告持续时间

--编辑:回复cmets--

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

客户端测量代码:

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()
  }
}

集群构建代码:

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()))
}

还有一个我无法解释的观察结果。我在一个循环中运行了两个以相同方式(如上)执行相同查询的线程,唯一的区别是黄色线程在查询之间休眠 100 毫秒,而绿色线程在查询之间休眠 60 秒。绿色线程比黄色线程更频繁地达到低延迟(低于 1 秒)。

【问题讨论】:

  • 你用的是什么java驱动版本?
  • 您是否正在监视 JVM(主机端和客户端)中的垃圾收集事件?
  • 你能发布你查询 Cassandra 的 Java 代码吗?
  • 我第二个@JimMeyer。您可以发布您的可用 RAM 和 JVM 设置吗?他们是否关注best practices as outlined by Datastax
  • 我将问题追踪到远程数据中心的节点上的查询超时。集群在两个 DC 中有节点,但 keyspace 仅在本地 DC 内复制,因此甚至考虑删除节点是令人惊讶的。我能够通过 (a) 从 ONE 更改为 LOCAL_ONE 一致性和 (b) 从普通的循环负载均衡器更改为 DC 感知的(也使用延迟感知和令牌感知)来降低延迟。为什么驱动程序会尝试联系远程主机以获得非复制的密钥空间?

标签: java cassandra driver cql cqlsh


【解决方案1】:

当你得到一个组件来测试自己时,这是一个常见的问题。

  • 您可能会遇到相关工具看不到的延迟。
  • 您的组件不知道应该何时开始请求。
  • 当 JVM 停止时,这可能会阻止您看到您尝试测量的延迟。

最可能的解释是第二种。假设您有 100 个任务的队列,但由于系统运行缓慢,每个任务需要 1 秒。您在内部对每个任务进行计时,发现它需要 1 秒,但是将 100 个任务添加到队列中,第一个任务在 0 秒后开始,但最后一个在 99 秒后开始,然后报告它花了 1 秒,但从您的角度来看完成需要 100 秒,其中 99 秒正在等待开始。

结果也可能会延迟到达您的手中,但这不太可能,除非您在处理结果时执行的操作超过数据库所需的操作。也就是说,您可能会认为瓶颈在服务器上。

【讨论】:

  • 如果“组件”(Cassandra 集群)认为它可以快速响应,但客户认为并非如此,我可以看到这种推理是适用的。在我的情况下,我有两个不同的客户端在同一台机器上运行,并测量它们与“组件”的交互,一个客户端始终快速地获得响应,另一个客户端看到很大的延迟。
【解决方案2】:

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

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

在我看来,Java 驱动程序中的一个错误仍然是,它尝试使用来自远程数据中心的节点作为协调节点,而该数据中心中显然不存在密钥空间。此外,即使以某种方式不可能做到这一点,我也在使用延迟感知策略,这应该将远程 DC 节点排除在考虑之外。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-12
    • 1970-01-01
    • 2018-11-24
    • 2017-08-06
    • 1970-01-01
    • 2017-08-25
    相关资源
    最近更新 更多