【问题标题】:Cassandra Reads seem to slowCassandra 阅读速度似乎变慢了
【发布时间】:2014-06-23 17:03:59
【问题描述】:

我正在分析一个使用 Cassandra 的应用程序,结果发现读取是瓶颈。经过仔细检查,它们似乎需要很长时间,我真的很感激能帮助我理解原因。

应用程序总是读取给定分区键的整组行(查询格式为SELECT * FROM table WHERE partition_key = ?)。不出所料,阅读时间是O(number of rows for partition key),但是这个常数似乎太高了。在检查了查询计划之后,结果发现大部分时间都花在了“合并来自 mem 和 sstables 的数据”上。

对于约 5000 行的分区键,此步骤需要 200 多毫秒,其中一行由 9 列组成,并且小于 100 字节。考虑到 SSD 的读取吞吐量,顺序读取 0.5MB 应该会立即发生。

实际上,我怀疑这根本与 I/O 有关。这台机器曾经有一个旋转磁盘,现在换成了 SSD。更改对查询性能没有影响。我认为 Cassandra 处理或它如何读取磁盘数据的方式非常复杂,这使得该操作非常昂贵。

从多个 SSTable 合并或迭代墓碑单元并不能解释这一点。首先,它应该花费几毫秒,其次这一切都在持续发生,无论是 2 个还是 4 个 SSTable,以及是否有墓碑单元。

提供一些背景知识:

硬件: 运行 Cassandra 的机器是一个 8 核、裸机和 SSD 支持的机器。我从机器上的 cqlsh 查询,数据存储在本地。它没有其他负载,查看 iostats,也几乎没有任何 i/o。

数据模型: 分区键PKtext 类型,主键是分区键和bigintK 的组合,而其余是 7 个可变列。下面列出了架构创建命令。

CREATE TABLE inboxes (
  PK text,
  K bigint,
  A boolean,
  B boolean,
  C boolean,
  D boolean,
  E bigint,
  E bigint,
  F int,
  PRIMARY KEY (PK, K)
  ) WITH CLUSTERING ORDER BY (K DESC));

这是一个示例跟踪,涉及 3 个 SSTable,相当多的墓碑。

activity                                                                                  | timestamp    | source      | source_elapsed
-------------------------------------------------------------------------------------------+--------------+-------------+----------------
                                                                        execute_cql3_query | 03:14:07,507 | 10.161.4.77 |              0
                            Parsing select * from table where PK = 'key_value' LIMIT 10000;| 03:14:07,508 | 10.161.4.77 |            123
                                                                       Preparing statement | 03:14:07,508 | 10.161.4.77 |            244
                                                 Executing single-partition query on table | 03:14:07,509 | 10.161.4.77 |           1155
                                                              Acquiring sstable references | 03:14:07,509 | 10.161.4.77 |           1173
                                                               Merging memtable tombstones | 03:14:07,509 | 10.161.4.77 |           1195
                                                            Key cache hit for sstable 2906 | 03:14:07,509 | 10.161.4.77 |           1231
                                               Seeking to partition beginning in data file | 03:14:07,509 | 10.161.4.77 |           1240
                                                            Key cache hit for sstable 1533 | 03:14:07,509 | 10.161.4.77 |           1550
                                               Seeking to partition beginning in data file | 03:14:07,509 | 10.161.4.77 |           1561
                                                            Key cache hit for sstable 1316 | 03:14:07,509 | 10.161.4.77 |           1867
                                               Seeking to partition beginning in data file | 03:14:07,509 | 10.161.4.77 |           1878
                                                Merging data from memtables and 3 sstables | 03:14:07,510 | 10.161.4.77 |           2180
                                                  Read 5141 live and 1944 tombstoned cells | 03:14:07,646 | 10.161.4.77 |         138734
                                                                          Request complete | 03:14:07,742 | 10.161.4.77 |         235030

【问题讨论】:

  • 尽可能粘贴跟踪
  • @RussS 使用示例跟踪更新了一个问题。这个实际上要快一点,但在我看来,调用的最后两个元素仍然需要很长时间。
  • 1.使用某些现有分区 ID 时的响应时间是多少? Cassandra 必须遍历内存部分、sstables 和 tombsones,并且它还使用布隆过滤器,这可能需要一些时间才能找到任何东西。 2. 你的数据结构是什么?所有数据中是否有很多更新、删除等。由于 cassandra 中的一切都是不可变的,因此可以触摸很多项目来发现什么都没有找到。
  • @MartinPodval 几乎没有任何删除,有不少更新/插入。正如我所说的 i/o 并没有真正注册(所以那里没有瓶颈),盒子上的负载是最小的,在我给出的跟踪中,当发现数据时读取和处理需要时间。您阅读 200 毫秒。作为比较,在同一类盒子上,以 5000req/s 的速度对 5000 个对象进行排序,其 p99 为 7ms。
  • 你用的是什么版本?

标签: database performance cassandra latency nosql


【解决方案1】:

您不只是“按顺序读取 0.5MB”,而是要求 Cassandra 将其转换为行,过滤掉墓碑(已删除的行),并将其转换为结果集。每行 0.04ms 相当合理;对于整个查询,我的经验法则是每 10 行 0.5 毫秒。

请记住,Cassandra 针对适合在线应用程序的短请求进行了优化; 10 到 100 行结果集是典型的。单个查询中没有并行化。

【讨论】:

  • 有机会获得有关您描述的操作的更详细数据吗?我问的原因是因为我得到了使用查询结果的应用程序的指标。它必须反序列化通过网络发送的结果,将其转换为域表示,以不同的顺序对行进行排序,应用几个过滤器,最后再次序列化。然而,它只是增加了一个数量级。
  • 我不明白这个问题;你能澄清一下吗?
  • 基本上,我添加的跟踪表明合并 3 个 SSTables 和 1 个 Memtable(共包含约 6000 个对象)需要 135 毫秒,然后读取(返回约 5000 个对象)需要额外的 1000 毫秒。我很想知道这两个步骤的组成以及子步骤需要多少时间。
猜你喜欢
  • 1970-01-01
  • 2016-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-15
  • 2012-07-30
  • 2015-01-07
相关资源
最近更新 更多