Cassandra 读取性能随时间缓慢下降

Cassandra read perfomance slowly decreases over time

我们有一个 Cassandra 集群,它由六个节点组成,每个节点有 4 个 CPU 和 16 Gb RAM 以及底层共享存储 (SSD)。我知道共享存储被认为对 Cassandra 来说是一种不好的做法,但我们的读取级别限制在 3 Gb/s 并且似乎可以可靠地满足紧急磁盘要求。

Cassandra 用作连续流处理的操作数据库。

最初 Cassandra 在 ~1,700 rps 处理请求,它看起来不错:

初始proxyhistograms:

但几分钟后性能开始下降,在接下来的两个小时内性能下降了三倍多。

同时我们观察到IOWait时间增加:

proxyhistograms显示如下图:

我们无法理解这种行为背后的原因。感谢任何帮助。

已编辑:

Table 定义:

CREATE TABLE IF NOT EXISTS subject.record(
    subject_id UUID,
    package_id text,
    type text,
    status text,
    ch text,
    creation_ts timestamp,
    PRIMARY KEY((subject_id, status), creation_ts)
) WITH CLUSTERING ORDER BY (creation_ts DESC);

CREATE TABLE IF NOT EXISTS subject.c_record(
    c_id UUID,
    s_id UUID,
    creation_ts timestamp,
    ch text,
    PRIMARY KEY(c_id, creation_ts, s_id)
) WITH CLUSTERING ORDER BY (creation_ts DESC);

CREATE TABLE IF NOT EXISTS subject.s_by_a(
    s int,
    number text,
    hold_number int,
    hold_type text,
    s_id UUID,
    PRIMARY KEY(
        (s, number),
        hold_type,
        hold_number,
        s_id
    )
);

far from 100 Mb

虽然有些人对此有不同的看法,但将分区保持在 1MB 到 2MB 的范围内是最佳的。 Cassandra 在返回大型结果集时通常表现不佳。保持分区大小较小,有助于查询更好地执行。

不知道查询是什么 运行,我 可以 说查询会随着时间的推移而恶化...... time 通常是问题所在。以这个 PRIMARY KEY 定义为例:

PRIMARY KEY((subject_id, status), creation_ts)

这是告诉 Cassandra 将数据存储在一个分区中(从 subject_idstatus 的串联散列),然后按 creation_ts 排序并强制执行唯一性。这里可能发生的是,似乎没有一种固有的方法来限制 分区的大小。由于集群键是时间戳,每个新条目(到特定分区)都会导致它随着时间的推移变得越来越大。

此外,status 根据定义是临时的,可能会发生变化。为此,必须在每次状态更新时删除并重新创建分区。当像这样建模系统时,我通常建议 status 列作为具有二级索引的非键列。虽然 Cassandra 中的二级索引也不是一个很好的解决方案,但如果结果集不是太大,它可以工作。

对于这种情况,采用“分桶”方法会有所帮助。本质上,选择一个时间组件进行分区,从而确保分区不会无限增长。

PRIMARY KEY((subject_id, month_bucket), creation_ts)

在这种情况下,应用程序写入时间戳 (creation_ts) 和当前月份 (month_bucket)。这有助于确保您永远不会在单个分区中放置超过一个月的数据。

现在这只是一个例子。就您而言,整整一个月可能太多了。它可能需要更小,具体取决于您的要求。根据所需的粒度,按周、天甚至小时对时间驱动的数据进行分区的情况并不少见。