【问题标题】:Does Cassandra 0.7.2 have performance issues with get_range_slices?Cassandra 0.7.2 的 get_range_slices 是否存在性能问题?
【发布时间】:2011-07-19 09:27:57
【问题描述】:

我有一个应用程序可以将数十亿条记录写入 Cassandra 并按键删除重复项。然后它在连续的阶段按其他字段(例如标题)对它们进行分组,以便可以对相似记录组进行进一步处理。该应用程序分布在一组机器上,因为我需要它在合理的时间(几小时而不是几周)内完成。

应用程序的一个阶段是使用 hector 客户端将记录写入 Cassandra,并将记录存储在列族中,并使用记录的主键作为 Cassandra 键。时间戳设置为记录的最后更新日期,因此我只能获取每个键的最新记录。

后期阶段需要从 Cassandra 中读回所有内容,对记录执行一些处理,并使用各种其他键将记录添加回不同的列族,以便对记录进行分组。

我通过使用 Cassandra.Client.describe_ring() 来确定环中的哪台机器是哪个 TokenRange 的主机,从而完成了这个批量读取。然后,我将每个 TokenRange 的 master 与 localhost 进行比较,以找出本地机器拥有哪些令牌范围(远程读取对于这种类型的批处理来说太慢了)。一旦我知道本地每台机器上有哪些 TokenRanges,我就会使用 Cassandra.Client.describe_splits() 获得均匀大小的分割。

一旦我有一堆可以从本地 Cassandra 实例读取的大小均匀的拆分,我就开始尽可能快地使用 Cassandra.Client.get_range_slices() 和 ConsistencyLevel.ONE 读取它们,这样就不需要了进行任何远程读取。我一次获取 100 行,依次遍历整个 TokenRange(我尝试了各种批量大小,100 似乎最适合这个应用程序)。

这一切都在 Cassandra 0.7.0 上运行良好,只需稍微调整内存大小和列族配置。以这种方式,我每秒可以读取 4000 到 5000 条记录,并使本地磁盘尽可能地工作。

这是我在 Cassandra 0.7.0 下看到的拆分示例和速度:

10/12/20 20:13:08 INFO m4.BulkCassandraReader: split - 20253030905057371310864605462970389448 : 21603066481002044331198075418409137847
10/12/20 20:13:08 INFO m4.BulkCassandraReader: split - 21603066481002044331198075418409137847 : 22954928635254859789637508509439425340
10/12/20 20:13:08 INFO m4.BulkCassandraReader: split - 22954928635254859789637508509439425340 : 24305566132297427526085826378091426496
10/12/20 20:13:08 INFO m4.BulkCassandraReader: split - 24305566132297427526085826378091426496 : 25656389102612459596423578948163378922
10/12/20 20:13:08 INFO m4.BulkCassandraReader: split - 25656389102612459596423578948163378922 : 27005014429213692076328107702662045855
10/12/20 20:13:08 INFO m4.BulkCassandraReader: split - 27005014429213692076328107702662045855 : 28356863910078000000000000000000000000
10/12/20 20:13:18 INFO m4.TagGenerator: 42530 records read so far at a rate of 04250.87/s
10/12/20 20:13:28 INFO m4.TagGenerator: 90000 records read so far at a rate of 04498.43/s
10/12/20 20:13:38 INFO m4.TagGenerator: 135470 records read so far at a rate of 04514.01/s
10/12/20 20:13:48 INFO m4.TagGenerator: 183946 records read so far at a rate of 04597.16/s
10/12/20 20:13:58 INFO m4.TagGenerator: 232105 records read so far at a rate of 04640.62/s

当我升级到 Cassandra 0.7.2 时,我不得不重新构建配置,因为有一些新选项等,但我小心翼翼地尝试从 0.7.0 配置中获取所有相关的调整设置工作。但是,使用新版本的 Cassandra,我每秒几乎无法读取 50 条记录。

这是我现在在 Cassandra 0.7.2 下看到的拆分和速度示例:

21:02:29.289 [main] INFO  c.p.m.a.batch.BulkCassandraReader - split - 50626015574749929715914856324464978537 : 51655803550438151478740341433770971587
21:02:29.290 [main] INFO  c.p.m.a.batch.BulkCassandraReader - split - 51655803550438151478740341433770971587 : 52653823936598659324985752464905867108
21:02:29.290 [main] INFO  c.p.m.a.batch.BulkCassandraReader - split - 52653823936598659324985752464905867108 : 53666243390660291830842663894184766908
21:02:29.290 [main] INFO  c.p.m.a.batch.BulkCassandraReader - split - 53666243390660291830842663894184766908 : 54679285704932468135374743350323835866
21:02:29.290 [main] INFO  c.p.m.a.batch.BulkCassandraReader - split - 54679285704932468135374743350323835866 : 55681782994511360383246832524957504246
21:02:29.291 [main] INFO  c.p.m.a.batch.BulkCassandraReader - split - 55681782994511360383246832524957504246 : 56713727820156410577229101238628035242
21:09:06.910 [Thread-0] INFO  c.p.m.assembly.batch.TagGenerator - 100 records read so far at a rate of 00000.25/s
21:13:00.953 [Thread-0] INFO  c.p.m.assembly.batch.TagGenerator - 10100 records read so far at a rate of 00015.96/s
21:14:53.893 [Thread-0] INFO  c.p.m.assembly.batch.TagGenerator - 20100 records read so far at a rate of 00026.96/s
21:16:37.451 [Thread-0] INFO  c.p.m.assembly.batch.TagGenerator - 30100 records read so far at a rate of 00035.44/s
21:18:35.895 [Thread-0] INFO  c.p.m.assembly.batch.TagGenerator - 40100 records read so far at a rate of 00041.44/s

正如您可能从日志中看到的,代码已移至不同的包,但除此之外代码没有更改。它运行在相同的硬件上,所有的内存设置都是一样的。

我可以看到 Cassandra 版本之间的一些性能差异,但是像这样令人震惊的事情(100 倍的性能下降)似乎我必须缺少一些基本的东西。即使在 0.7.0 上调整列族和内存设置之前,它也从来没有那么慢。

有谁知道这是什么原因?是否有一些我可能会丢失的调整设置可能会导致这种情况? Cassandra 功能是否发生了变化以支持未记录的 hadoop?通读发行说明,我找不到任何可以解释这一点的东西。任何有关解决此问题的帮助,甚至只是解释它可能停止工作的原因都将不胜感激。

【问题讨论】:

    标签: performance cassandra batch-processing


    【解决方案1】:

    我想我应该关闭这个循环,因为我们已经找到了问题的根源,问题不是 Cassandra 问题,而是配置问题。

    当我们升级到 0.7.2 时,我错过了一项更改的配置,那就是令牌环。在我们的 0.7.0 配置中,我们的第一个令牌为 2^127 / 12,而在我们的 0.7.2 配置中,我们的第一个令牌为 0。这导致一个节点获得了 0:0 的拆分。 0:0 似乎是一个神奇的范围,它要求 Cassandra 提供一切。所以我们在集群中有一个节点通过网络提取所有数据。该节点的网络流量最终导致我们找到问题的根源。

    修复是更正代码以检查 0:0 情况并进行处理,因此代码现在将处理以任一方式分区的 Cassandra 集群(第一个节点为 0 或其他)。

    简而言之,这不是 Cassandra 的问题。我的配置问题。

    【讨论】:

      【解决方案2】:

      这里不响铃。我的猜测是你遇到了诚实的回归。

      您可以尝试将磁盘访问模式切换为标准。您也可以尝试禁用 JNA。 (这些应该分别绕过 1713 和 1470,它们是最有可能的罪魁祸首。但是,这里的“最有可能”只是程度问题,我可能给出 20% 的几率。)

      如果您可以使用 contrib/stress 将缓慢归结为可见的东西,那么我们可以从那开始逆向寻找原因。但是,如果您只能使用自己的设置进行复制,则必须一分为二(通过提交进行二进制搜索、部署构建并检查性能)以找出导致这种回归的原因。

      为了将来参考,Cassandra 用户列表是一个比 StackOverflow 更好的论坛,用于讨论“我认为我发现了一个错误”。那里有更多的专业知识。

      【讨论】:

      • 感谢您的建议。这让我想到了一些可以尝试的事情,并让我记住了一些事情。我记得我在尝试对 OutOfMemoryError 进行故障排除时将 disk_access_mode: mmap_index_only 设置为 0.7.0,然后我将此配置更改传播到 0.7.2 配置。我从未在 0.7.0 上安装过 JNA,因为我没有需要它的性能问题,而且我也将它带入了 0.7.2。我在 cassandra 日志中看到一条注释:INFO [main] 2011-03-20 20:21:37,412 CLibrary.java (line 61) JNA not found。本机方法将被禁用。
      • 好吧,我在安装 JNA 并使用 mmap 和标准磁盘访问的情况下进行了尝试。没有成功。不幸的是,时间压力不允许我找到这个的根本原因。我将不得不恢复到 0.7.0 并接受我将无法获得错误修复和改进。我讨厌这样做,但总是比由于“不可预见的问题”而延迟交付已经承诺的工作更容易稍后申请时间来解决可能需要升级 Cassandra 的未来问题。
      猜你喜欢
      • 2017-09-07
      • 1970-01-01
      • 2016-11-29
      • 2017-04-23
      • 2016-02-10
      • 2020-01-26
      • 2012-03-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多