官方地址: Storage Engine

存储引擎

参考: Cassandra 写机制

Cassandra流程图

  1. cassandra 首先将客户端提交的数据和操作记录写入到 commitLog,其目的是:为了提升可靠性,起到数据恢复的作用

  2. 接着 cassandra 将数据写入到 内存表 memtable 中, memtable 中 组织的数据 按照 key 排序。当 memtable 中的数据到达一定限制后(周期性 / 批量)flush 到 一个 SSTable 中。 这种机制,相当于 缓存 写回机制(write back cache),目的在于:将随机 IO 写改为 顺序 IO 写,大大降低了 写操作对于存储系统的压力。

  3. SSTable 写入成功之后,不可变更,只能读取,因此对于 Cassandra 而言,只有 顺序写,没有随机写 操作

  4. 由于 SSTbale 的只读性,因此 同一个 Column Family 的数据可能存储在 多个 SSTable 中,如果一个 Column Family 中的数据量很大的时候,此时 Cassandra 会合并读取多个 SSTable 和 Memtable ,导致 查询的效率 严重下降。

  5. 在 4 的基础上:因此,cassandra 引入了 BloomFilter ,每个 SSTable 都会有一个 BloomFilter , 是一个存储在 内存中的数据结构,它可以快速判断某个给定的 key 是否位于 某个 SSTable 中,因此,Cassandra 能够 快速定位 某个 key 对应的 SSTable

  6. 为了避免大量SSTable带来的性能影响,Cassandra通过一种称为压缩(Compaction)的机制来处理随着时间推移而不断膨胀的SSTables。Cassandra定期将多个SSTable合并成一个SSTable,由于每个SSTable中的数据均是有序的,因此只要做一次合并排序就可以完成该任务,这个代价是可以接受的。

  7. Cassandra 的数据存储目录下,可以看到三种类型的文件,文件名的格式类似于:(Column Family Name-序号-Data.db / Column Family Name-序号-Filter.db / Column Family Name-序号-index.db). 其中Data.db 文件是 SSTable 数据文件,SSTable 是 Sorted Strings Table 的缩写,按照key 排序后存储 key/value 键值字符串。index.db 是索引文件,保存的是每个 key 在数据文件中的偏移位置,而 Filter.db 则是 Bloom Filter 算法生产的映射文件。


CommitLog

提交日志是 Cassandra 节点本地所有突变的仅追加日志。写入 Cassandra 的所有数据都将首先写入提交日志,然后再写入内存表。这在意外关机的情况下提供了耐用性。启动时,提交日志中的任何突变都将应用于内存表。

所有数据写入操作都通过存储在commitlog段中进行优化,,从而减少了写入磁盘所需的查找次数。提交日志段受commitlog_segment_size_in_mb选项限制,一旦达到大小,就会创建一个新的提交日志段。一旦将所有Commitlog数据刷新到SSTables后,就可以对其进行归档,删除或回收。当 Cassandra 将数据早于特定点写入 SSTables 时, Commitlog 段将被截断。在停止 Cassandra 之前运行 nodetoolrain 将把 memtables 中的所有内容写入 SSTables ,并且无需在启动时与提交日志同步。

  • commitlog_segment_size_in_mb: 默认大小为32,几乎总是可以的,但是,如果要归档提交日志段(请参见commitlog_archiving.properties),则可能需要更精细的归档粒度。8或16 MB是合理的。还可以通过cassandra.yaml中的 max_mutation_size_in_kb 设置来配置最大突变大小。默认值为 commitlog_segment_size_in_mb * 1024 的一半。

    注意:如果明确设置了max_mutation_size_in_kb,则commitlog_segment_size_in_mb必须设置为至少两倍于max_mutation_size_in_kb / 1024

commitlog_sync

可以是: “periodic“ or “batch“ , 默认: batch

  • batch: 在 batch 模式下, Cassandra 不会应答(ack)写操作直到 commitlog 写到(fsync)磁盘上。它会在 fsyncs 之间等待 commitlog_sync_batch_window_in_ms 毫秒。这个窗口期应保持短,因为 writer 线程在等待时将无法完成额外的工作。出于同样的原因,您可能需要增加 concurrent_writes

    • commitlog_sync_batch_window_in_ms: 在 batch , fsyncs 之间等待的时间。默认值为 2
  • periodic: 在periodic模式下,写操作会被立即应答(ack),每 commitlog_sync_period_in_ms 毫秒都会简单地同步 CommitLog

    • commitlog_sync_period_in_ms:在periodic ,fsyncs之间等待的时间。默认值为 10000

如果发生意外关机, 则如果同步延迟, 则 Cassandra 可能会失去同步期间或更多的数据。如果使用 batch 模式, 建议将 commitlogs 存储在单独的存储设备中

commitlog_directory

在磁性机械硬盘(magnetic HDD)上运行时, 默认情况下此选项被注释掉,这个目录应该和data目录分开存放到不同的物理磁盘。如果未设置, 则默认目录为 $CASSANDRA _home/data/commitlog

commitlog_compression

压缩以应用于commitlog。 如果省略,则提交日志将被解压缩。 支持LZ4,Snappy和Deflate压缩器.

1
2
3
#   - class_name: LZ4Compressor
# parameters:
# -

commitlog_total_space_in_mb

commitlog 占用的总空间。如果使用的空间超过了这个值,Cassandra 转到下一个最近的段,刷新那些最旧的commitlog 段对应的 memtables 到磁盘中,删除这些log段。这减少了启动时重播的数据量,防止不经常更新的表不定期的保留commitlog段。一个小的commitlog总空间会导致不活跃的表产生更频繁的刷新活动

The default value is the smaller of 8192, and 1/4 of the total space of the commitlog volume.

Memtables

Memtables 是内存结构,作为 Cassandra 的写入缓冲。通常,每个表有一个活跃的 memtable 。最终,memtables 被刷新到磁盘上,成为不可变的 SSTables 。这可以通过多种方式触发:

  • memtables 的内存使用量超过配置的阈值( memtable_cleanup_threshold)
  • CommitLog 接近其最大大小,并强制执行 memtable 刷新以允许释放 commitlog

Memtables 可以完全存储在堆上或部分堆外存储,具体取决于 memtable_allocation_type

SSTables

SSTablesCassandra 用于在磁盘上保存数据的不可变数据文档。由于SSTablesMemtables刷新到磁盘或从其他节点流式传输,Cassandra会触发将多个SSTable组合成一个的压缩

由于SSTablesMemtables刷新到磁盘或从其他节点流式传输,因此Cassandra会触发压缩将多个SSTable组合成一个。 一旦编写了新的SSTable,就可以删除旧的SSTable

  • Data.db: ​ 实际数据, 即行的内容

  • Index.db: ​ 从分区键(partition keys)到Data.db文档中的位置的索引。对于宽分区,这可能还包括分区内行的索引

  • Summary.db: ​ Index.db文档中每128个条目(默认情况下)的采样

  • Filter.db: ​ SSTable中分区键(partition keys)的布隆过滤器(Bloom Filter)

  • CompressionInfo.db: ​ Data.db文档中的压缩块的偏移量和长度的元数据

  • Statistics.db: ​ 存储SSTable相关的元数据,包括时间戳,逻辑删除(tombstones),集群key,压缩,修复,压缩,TTL等信息

  • Digest.crc32: ​ Data.db文档的CRC-32摘要

  • TOC.txt: SSTable的组件文档的纯文本列表

Within the Data.db file, rows are organized by partition. These partitions are sorted in token order (i.e. by a hash of the partition key when the default partitioner, Murmur3Partition, is used). Within a partition, rows are stored in the order of their clustering keys.

可以选择使用基于块的压缩来压缩SSTable。