【问题标题】:Large data in Cassandra renders cluster unresponsiveCassandra 中的大数据导致集群无响应
【发布时间】:2016-12-23 14:33:20
【问题描述】:

我在 AWS 上的 Cassandra 2.2.0 中创建了一个结构简单的表:

CREATE TABLE data_cache (
    cache_id text,
    time timeuuid,
    request_json_data text,
    PRIMARY KEY (cache_id, time)
) WITH CLUSTERING ORDER BY (time DESC)
    AND bloom_filter_fp_chance = 0.01
    AND caching = '{"keys":"ALL", "rows_per_partition":"NONE"}'
    AND comment = ''
    AND compaction = {'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy'}
    AND compression = {'sstable_compression': 'org.apache.cassandra.io.compress.LZ4Compressor'}
    AND dclocal_read_repair_chance = 0.1
    AND default_time_to_live = 3600
    AND gc_grace_seconds = 86400
    AND max_index_interval = 2048
    AND memtable_flush_period_in_ms = 0
    AND min_index_interval = 128
    AND read_repair_chance = 0.0
    AND speculative_retry = '99.0PERCENTILE';

我在 AWS 上有 2 个数据中心 - eu 和 us-east。

我遇到的问题是表快速填满到系统上没有更多磁盘空间的程度。由于 READ 在 CQLSH 中变得不负责任,因此截断表也是有问题的。

如您所见 - 我将默认 TTL 更改为 3600 秒(或 1 小时),并将 GC 宽限秒数更改为短于默认的 10 天。

目前每个集群的数据为 101GB,系统变得无响应。 如果我尝试一个简单的select count(*) from data_cache,它会向我发送连接超时 - 在 3 次尝试后,集群本身就会丢失。错误日志指出 java 内存不足。

我应该做些什么不同的事情?我究竟做错了什么?

目前存在 TTL,因此数据不会破坏服务器,直到我们知道我们将使用缓存多长时间,因此为什么它只设置为 1 小时 - 但如果我们认为缓存应该构建 1 天 - 我们将相应地扩展容量,但我们还需要从中读取,由于崩溃,我们无法这样做。

【问题讨论】:

  • 您使用的是什么实例类型和存储?
  • 是的,Cassandra(或任何分布式数据库)中的SELECT COUNT(*)从不简单。不惜一切代价避免未绑定或多键查询。
  • @TommasoBarbugli m3.large。每个区域 4 台服务器。我有 2 个 DC。

标签: cassandra cassandra-2.2


【解决方案1】:

您所经历的一切都是意料之中的。 Cassandra 擅长检索一条特定记录,但不擅长一次检索数十亿行。事实上,您的简单 SELECT COUNT(*) FROM data_cache 正在读取您所有的数据集。由于 Cassandra 的性质,counting is hard

如果您同时通过cache_idtime 查询,一切都很好,但如果您不这样做,那就是自找麻烦,尤其是如果您不知道行的宽度。

请注意 TTL 会生成墓碑,它迟早会打击你。即使您降低了宽限期,TTL 也不能保证您的可用空间会被收集。实际上,使用默认参数,SizeTieredCompactionStrategy 需要 4 个大小大致相同的 SSTable,但如果您没有这样相等的表,那么压缩不会做任何事情。在最坏的情况下,SizeTieredCompactionStrategy 要求磁盘上的可用空间至少是要压缩的最大 CF 的大小

在我看来,您正在尝试将 Cassandra 用作缓存,但您目前正在像队列一样使用它。我会重新考虑数据模型。如果您带着更好的规格来到这里,也许我们可以为您提供帮助。

【讨论】:

  • 最初 - 模型是 cache_id, request_data。但是磁盘太容易超时并开始使系统崩溃。然后我随着时间的推移对其进行改造,以便我可以尝试随着时间的推移刷新数据并拥有它进入表内的最后一个时间戳。但是,在阅读了您的 cmets 之后-也许这是一个坏主意。
  • 您已经回答了为什么我所做的选择会导致节点无响应,但是您没有回答为什么尽管存在 TTL 磁盘却如此快速地填满。如果正在删除数据并且正在通过压缩以删除墓碑,那么 TTL 不应该确保我节省磁盘空间吗?
【解决方案2】:

我认为您的第一个问题与压缩有关,更准确地说是与写入吞吐量和压缩之间的比率有关。在 cassandra.yaml 文件中有一个字段compaction_throughput_mb_per_sec。如果它的值低于您的写入负载,Cassandra 将无法清除空间,最终将没有 dsik 空间和节点崩溃。

我想知道您的数据是否正确分布在您的集群中。我在这里看到您使用 PARTITION_KEY cache_id 和 CLUSTERING_KEY time。这意味着任何具有相同cache_id 的插入都会进入同一个节点。因此,如果您在同一 cache_id 中的 cache_id 太少或 time 太多,则工作负载将不会平均分配,并且存在节点无响应的风险。您必须牢记的限制是每个分区不超过 100 000 行,每个分区不超过 100 Mb。

【讨论】:

  • 我不知道 100k / 100Mb 的限制。我知道令牌大小及其与您拥有的节点数量的关系,但我一直认为 Cassandra 可以处理大量数据,还是假设您连接到它的服务器数量?
  • 这些不是硬性限制。它们出于性能原因而存在。它们是数据建模的(好的)经验法则。
  • @azngunit81 Cassandra 可以处理大量分区。但它不能很好地处理太大的分区(超过 100 000 条记录或 100 Mb)。您仍然可以通过添加分区键将一个分区拆分为多个分区。例如,您可以通过cache_idday 拥有一个分区:((cache_id, day), time)
  • @azngunit81 您是否尝试增加compaction_throughput_mb_per_sec 以更快地释放磁盘空间?
  • 尝试确定您提到的写入负载,以确定我可以增加多少
猜你喜欢
  • 2019-02-28
  • 2020-11-16
  • 2011-08-07
  • 2020-07-04
  • 2014-03-11
  • 2011-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多