Cassandra 中的 LeveledCompactionStrategy (LCS) 实现了 LevelDB 的内部结构。您可以在中查看具体的实施细节LevelDB实现文档 https://github.com/google/leveldb/blob/master/doc/impl.md.
为了给您一个简单的解释,请考虑以下几点:
- 每个 SSTable 都是在达到固定(相对较小)的大小限制时创建的。默认情况下L0获取5MB的文件,并且随后的每个级别都是 10 倍大小。 (在 L1 中,您将拥有 50MB 的数据,L2 中将有 500MB 的数据,依此类推)。
- SSTables 是用以下命令创建的保证它们不重叠
- 当一个级别填满时,会触发压缩,并将 L 级的马厩提升到 L+1 级。因此,在 L1 中,大约 10 个文件中将有 50MB,L2 中大约 100 个文件中将有 500MB,等等。
粗体字是证明从同一文件 (SSTable) 读取 90% 的合理性的相关详细信息。让我们一起算一算,一切都会变得更清楚。
假设 L0 中有键 A、B、C、D、E,每个键占用 1MB 的数据。
接下来我们插入键 F。由于级别 0 已填充,压缩将在级别 1 中创建一个包含 [A,B,C,D,E] 的文件,而 F 将保留在级别 0 中。
这相当于 L1 中 1 个文件中约 83% 的数据。
接下来我们插入 G,H,I,J 和 K。所以 L0 再次填满,L1 得到一个带有 [I,G,H,I,J] 的新 sstable。
现在 L0 中有 K,L1 有 [A,B,C,D,E] 和 [F,G,H,I,J]
这大约是 L1 中数据的 90%。
如果我们继续插入键,我们将遇到相同的行为,因此,这就是为什么您从大致相同的文件/SSTable 获得 90% 的读取服务。
我提到的链接上的本段给出了更深入和详细的信息(更新和墓碑会发生什么)(压缩选择的大小不同,因为它们是 LevelDB 默认值,而不是 C*s):
当级别 L 的大小超过其限制时,我们将其压缩到后台线程中。压缩从 L 级选取一个文件,并从下一个 L+1 级选取所有重叠文件。请注意,如果 L 级文件仅与 (L+1) 级文件的一部分重叠,则 (L+1) 级的整个文件将用作压缩的输入,并在压缩后将被丢弃。另外:因为 level-0 是特殊的(其中的文件可能会相互重叠),所以我们特别对待从 level-0 到 level-1 的压缩:一个 level-0 压缩可能会选择多个 level-0 文件,以防其中一些文件文件相互重叠。
压缩合并所选文件的内容以生成一系列级别 (L+1) 文件。当前输出文件达到目标文件大小 (2MB) 后,我们切换到生成新级别 (L+1) 文件。当当前输出文件的键范围增长到足以重叠超过十个级别(L+2)文件时,我们还会切换到新的输出文件。最后一条规则确保稍后压缩级别 (L+1) 文件不会从级别 (L+2) 中获取太多数据。