压缩
Cassandra 允许操作员在每个表的基础上配置压缩。压缩通过压缩用户可配置压缩的 SSTable 来减少磁盘上的数据大小 chunk_length_in_kb
。由于 Cassandra SSTable 是不可变的,因此压缩的 CPU 成本仅在写入 SSTable 时才需要 - 对数据的后续更新将落在不同的 SSTable 中,因此 Cassandra 在发出 UPDATE 命令时不需要解压缩、覆盖和重新压缩数据。在读取时,Cassandra 将在磁盘上找到相关的压缩块,解压缩整个块,然后继续执行读取路径的其余部分(合并来自磁盘和内存表的數據,读取修复等)。
压缩算法通常在以下三个方面进行权衡
-
压缩速度:压缩算法压缩数据的速度有多快。这在刷新和压缩路径中至关重要,因为数据必须在写入磁盘之前进行压缩。
-
解压缩速度:压缩算法解压缩数据的速度有多快。这在读取和压缩路径中至关重要,因为数据必须从磁盘上以完整的块读取并解压缩才能返回。
-
比率:未压缩数据减少的比率是多少。Cassandra 通常将其衡量为磁盘上的数据大小相对于未压缩大小的比率。例如,比率为
0.5
表示磁盘上的数据大小是未压缩数据大小的 50%。Cassandra 将每个表的此比率公开为nodetool tablestats
的SSTable Compression Ratio
字段。
默认情况下,Cassandra 提供五种压缩算法,它们在这些方面进行了不同的权衡。虽然压缩算法的基准测试取决于许多因素(算法参数,如压缩级别、输入数据的可压缩性、底层处理器类别等……),但下表可以帮助您根据应用程序的要求选择一个起点,并对不同的选择在这些方面的性能进行非常粗略的评级(A 相对较好,F 相对较差)
压缩算法 | Cassandra 类 | 压缩 | 解压缩 | 比率 | C* 版本 |
---|---|---|---|---|---|
|
A+ |
A+ |
C+ |
|
|
|
C+ |
A+ |
B+ |
|
|
|
A- |
A- |
A+ |
|
|
|
A- |
A |
C |
|
|
|
C |
C |
A |
|
一般来说,对于性能关键型(延迟或吞吐量)应用程序,LZ4
是正确的选择,因为它在每个 CPU 周期上都能获得出色的比率。这就是为什么它是 Cassandra 中的默认选择。
但是,对于存储关键型应用程序(磁盘占用空间),Zstd
可能是更好的选择,因为它可以获得比 LZ4
更高的比率。
Snappy
保留用于向后兼容,LZ4
通常是更好的选择。
Deflate
保留用于向后兼容,Zstd
通常是更好的选择。
配置压缩
压缩在每个表的基础上配置为 CREATE TABLE
或 ALTER TABLE
的可选参数。所有压缩器都有三个选项可用
-
class
(默认:LZ4Compressor
):指定要使用的压缩类。两个“快速”压缩器是LZ4Compressor
和SnappyCompressor
,两个“良好”比率压缩器是ZstdCompressor
和DeflateCompressor
。 -
chunk_length_in_kb
(默认:16KiB
):指定每个压缩块的数据的千字节数。这里的主要权衡是,更大的块大小为压缩算法提供了更多上下文并提高了它们的比率,但需要读取更多数据才能反序列化和读取更多数据。
LZ4Compressor
支持以下附加选项
-
lz4_compressor_type
(默认fast
):指定我们应该使用high
(也称为LZ4HC
)比率版本还是fast
(也称为LZ4
)版本的LZ4
。high
模式支持可配置的级别,这允许操作员通过lz4_high_compressor_level
选项调整性能 <→ 比率权衡。请注意,在4.0
及更高版本中,最好使用Zstd
压缩器。 -
lz4_high_compressor_level
(默认9
):一个介于1
和17
(含)之间的数字,表示要花费多少 CPU 时间来尝试获得更高的压缩比率。通常,较低的级别“更快”,但它们获得的比率较低,而较高的级别较慢,但获得的压缩比率较高。
ZstdCompressor
支持以下附加选项
-
compression_level
(默认3
):一个介于-131072
和22
(含)之间的数字,表示要花费多少 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 TABLE
将 enabled
设置为 false
来禁用压缩
ALTER TABLE keyspace.table
WITH compression = {'enabled':'false'};
但是,操作员应该意识到,更改压缩不是立即生效的。数据在写入 SSTable 时被压缩,并且由于 SSTable 是不可变的,因此压缩在表被压缩之前不会被修改。在通过 ALTER TABLE
发出对压缩选项的更改后,现有的 SSTable 不会被修改,直到它们被压缩 - 如果操作员需要压缩更改立即生效,操作员可以使用 nodetool scrub
或 nodetool 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 开销可能是限制因素。
-
为了防止慢速压缩器(
Zstd
、Deflate
、LZ4HC
)阻塞刷新时间过长,所有三个压缩器都使用默认的快速LZ4
压缩器进行刷新,然后依靠正常的压缩将数据重新压缩到所需的压缩策略。有关更多详细信息,请参阅 CASSANDRA-15379。 -
压缩路径对数据进行校验和以确保正确性 - 传统的 Cassandra 读取路径没有办法确保磁盘上数据的正确性,而压缩表允许用户设置
crc_check_chance
(0.0 到 1.0 之间的浮点数),使 Cassandra 能够在读取时概率性地验证块,以验证磁盘上的位是否损坏。