Cassandra 文档

版本

您正在查看预发布版本的文档。

压缩

Cassandra 允许操作员在每个表的基础上配置压缩。压缩通过压缩用户可配置压缩的 SSTable 来减少磁盘上的数据大小 chunk_length_in_kb。由于 Cassandra SSTable 是不可变的,因此压缩的 CPU 成本仅在写入 SSTable 时才需要 - 对数据的后续更新将落在不同的 SSTable 中,因此 Cassandra 在发出 UPDATE 命令时不需要解压缩、覆盖和重新压缩数据。在读取时,Cassandra 将在磁盘上找到相关的压缩块,解压缩整个块,然后继续执行读取路径的其余部分(合并来自磁盘和内存表的數據,读取修复等)。

压缩算法通常在以下三个方面进行权衡

  • 压缩速度:压缩算法压缩数据的速度有多快。这在刷新和压缩路径中至关重要,因为数据必须在写入磁盘之前进行压缩。

  • 解压缩速度:压缩算法解压缩数据的速度有多快。这在读取和压缩路径中至关重要,因为数据必须从磁盘上以完整的块读取并解压缩才能返回。

  • 比率:未压缩数据减少的比率是多少。Cassandra 通常将其衡量为磁盘上的数据大小相对于未压缩大小的比率。例如,比率为 0.5 表示磁盘上的数据大小是未压缩数据大小的 50%。Cassandra 将每个表的此比率公开为 nodetool tablestatsSSTable Compression Ratio 字段。

默认情况下,Cassandra 提供五种压缩算法,它们在这些方面进行了不同的权衡。虽然压缩算法的基准测试取决于许多因素(算法参数,如压缩级别、输入数据的可压缩性、底层处理器类别等……),但下表可以帮助您根据应用程序的要求选择一个起点,并对不同的选择在这些方面的性能进行非常粗略的评级(A 相对较好,F 相对较差)

压缩算法 Cassandra 类 压缩 解压缩 比率 C* 版本

LZ4

LZ4Compressor

A+

A+

C+

>=1.2.2

LZ4HC

LZ4Compressor

C+

A+

B+

>= 3.6

Zstd

ZstdCompressor

A-

A-

A+

>= 4.0

Snappy

SnappyCompressor

A-

A

C

>= 1.0

Deflate (zlib)

DeflateCompressor

C

C

A

>= 1.0

一般来说,对于性能关键型(延迟或吞吐量)应用程序,LZ4 是正确的选择,因为它在每个 CPU 周期上都能获得出色的比率。这就是为什么它是 Cassandra 中的默认选择。

但是,对于存储关键型应用程序(磁盘占用空间),Zstd 可能是更好的选择,因为它可以获得比 LZ4 更高的比率。

Snappy 保留用于向后兼容,LZ4 通常是更好的选择。

Deflate 保留用于向后兼容,Zstd 通常是更好的选择。

配置压缩

压缩在每个表的基础上配置为 CREATE TABLEALTER TABLE 的可选参数。所有压缩器都有三个选项可用

  • class(默认:LZ4Compressor):指定要使用的压缩类。两个“快速”压缩器是 LZ4CompressorSnappyCompressor,两个“良好”比率压缩器是 ZstdCompressorDeflateCompressor

  • chunk_length_in_kb(默认:16KiB):指定每个压缩块的数据的千字节数。这里的主要权衡是,更大的块大小为压缩算法提供了更多上下文并提高了它们的比率,但需要读取更多数据才能反序列化和读取更多数据。

LZ4Compressor 支持以下附加选项

  • lz4_compressor_type(默认 fast):指定我们应该使用 high(也称为 LZ4HC)比率版本还是 fast(也称为 LZ4)版本的 LZ4high 模式支持可配置的级别,这允许操作员通过 lz4_high_compressor_level 选项调整性能 <→ 比率权衡。请注意,在 4.0 及更高版本中,最好使用 Zstd 压缩器。

  • lz4_high_compressor_level(默认 9):一个介于 117(含)之间的数字,表示要花费多少 CPU 时间来尝试获得更高的压缩比率。通常,较低的级别“更快”,但它们获得的比率较低,而较高的级别较慢,但获得的压缩比率较高。

ZstdCompressor 支持以下附加选项

  • compression_level(默认 3):一个介于 -13107222(含)之间的数字,表示要花费多少 CPU 时间来尝试获得更高的压缩比率。级别越低,速度越快(以比率为代价)。从 20 到 22 的值称为“超级别”,应谨慎使用,因为它们需要更多内存。默认值 3 是与 Deflate 比率竞争的良好选择,而 1 是与 LZ4 竞争的良好选择。

用户可以使用以下语法设置压缩

CREATE TABLE keyspace.table (id int PRIMARY KEY)
   WITH compression = {'class': 'LZ4Compressor'};

或者

ALTER TABLE keyspace.table
   WITH compression = {'class': 'LZ4Compressor', 'chunk_length_in_kb': 64};

启用后,可以使用 ALTER TABLEenabled 设置为 false 来禁用压缩

ALTER TABLE keyspace.table
   WITH compression = {'enabled':'false'};

但是,操作员应该意识到,更改压缩不是立即生效的。数据在写入 SSTable 时被压缩,并且由于 SSTable 是不可变的,因此压缩在表被压缩之前不会被修改。在通过 ALTER TABLE 发出对压缩选项的更改后,现有的 SSTable 不会被修改,直到它们被压缩 - 如果操作员需要压缩更改立即生效,操作员可以使用 nodetool scrubnodetool upgradesstables -a 触发 SSTable 重写,这两者都将重建磁盘上的 SSTable,并在过程中重新压缩数据。

其他选项

  • crc_check_chance(默认:1.0):确定 Cassandra 在读取期间验证每个压缩块上的校验和的可能性,以防止数据损坏。除非您有配置文件表明这是一个性能问题,否则强烈建议不要关闭它,因为它是 Cassandra 唯一防止位腐烂的保护措施。在早期版本的 Cassandra 中,压缩配置中存在此选项的副本。后者在 Cassandra 3.0 中被弃用,并在 Cassandra 5.0 中被删除。

优势和用途

压缩的主要优势是它减少了写入磁盘的数据量。减少的大小不仅节省了存储需求,而且通常还会提高读写吞吐量,因为压缩数据的 CPU 开销比从磁盘读取或写入更大数量的未压缩数据所需的时间更快。

压缩在包含许多行的表中最有用,其中这些行本质上相似。包含相似文本列(如重复的 JSON blob)的表通常压缩得很好。包含已压缩数据或随机数据(例如基准数据集)的表通常压缩得不好。

操作影响

  • 压缩元数据存储在非堆内存中,并随磁盘上的数据进行扩展。这通常需要每 TB 磁盘数据 1-3 GB 的非堆内存,尽管确切的用法会因 chunk_length_in_kb 和压缩比率而异。

  • 流式传输操作涉及压缩和解压缩压缩表上的数据 - 在某些代码路径(如非 vnode 引导)中,压缩的 CPU 开销可能是限制因素。

  • 为了防止慢速压缩器(ZstdDeflateLZ4HC)阻塞刷新时间过长,所有三个压缩器都使用默认的快速 LZ4 压缩器进行刷新,然后依靠正常的压缩将数据重新压缩到所需的压缩策略。有关更多详细信息,请参阅 CASSANDRA-15379

  • 压缩路径对数据进行校验和以确保正确性 - 传统的 Cassandra 读取路径没有办法确保磁盘上数据的正确性,而压缩表允许用户设置 crc_check_chance(0.0 到 1.0 之间的浮点数),使 Cassandra 能够在读取时概率性地验证块,以验证磁盘上的位是否损坏。

高级使用

高级用户可以通过实现 org.apache.cassandra.io.compress.ICompressor 接口来提供自己的压缩类。