Cassandra 的压缩策略STCS,LCS 和 DTCS

更新说明:
本文编写时最新的Cassandra版本为2.2,最新的稳定版本为2.1.8
2016年6月23日,增加一篇译文,当下最新版本为3.7

最新的Cassandra 2.1 或者更高的版本支持3种压缩策略,各有优劣,在2.2的版本的说明文档中,有对这三种策略的详细说明,部分翻译如下。
文档链接:http://docs.datastax.com/en/cassandra/2.2/cassandra/dml/dmlHowDataMaintain.html?scroll=dmlHowDataWritten_unique_2__types-compaction

[TCS]

SizeTieredCompactionStrategy (STCS)

  • 推荐在写密集负载中使用
  • 优势:在写密集的负载中工作良好
  • 劣势:可能把旧数据数据保持太久。随着时间的推移,需要的内存数量不断增长。

实际使用中如果内存不是很充裕,容易因为SSTable合并过程占用过多内存,导致内存不足,其他节点的Message无法和当前节点交换,最终导致节点宕机。我们可能在cassandra-env.sh中配置了一些参数控制内存的使用,但是并不能限制数据压缩的时候产生的内存损耗。多数建议是关闭自动SSTable压缩,改用手动在空闲期间进行压缩。

压缩过程

当有(默认4个)SSTable的大小相似的时候,STCS便会启动。压缩过程将这些SSTable合并成一个大的SSTable。当大的SSTable积累了足够数量,同样的过程会再次发生,组合成更大的SSTable。在任何时候,一些不同大小的SSTable的存在都是暂时的。这种策略在写密集的负载中工作良好,当需要读数据的时候,需要尝试读取多个SSTable来找到一行中的所有的数据。策略无法保证同一行的数据被限制在一小部分的sstable中。同时可以预测删除的数据是不均匀的,因为SSTable的大小是触发压缩的条件,并且SSTable可能增长的不够快以便合并旧的数据。当最大的那些SSTable达到一定大小,合并需要的内存也会增长为同时容纳新的SSTable+ 旧的SStable,可能会超出一个典型节点的内存总量。

LeveledCompactionStrategy (LCS)

  • 推荐在读密集负载中使用
  • 优势:内存的需求容易预测。读操作的延迟可以预计。旧数据更快的被驱逐。
  • 劣势:更高的io消耗可能引起操作延时。

实际上一般是又读又写,我觉得多数常见web应用可以用这个压缩方式。

LCS意在解决一些STCS在读操作上的一些问题。当SSTable的体积增长到一个不大的体积(默认5MB),它被写入第0级,L0,并且马上和第一级合并,L1。 在每个从L1开始的级别, 单个级别中所有的SSTable都确保没有重复数据。因为没有数据重复,LCS有时候会分割SSTable,就像合并他们时候一样,以确保文件大小相同。每个级别都是上一个级别大小的10倍, 所以L1 将会是 L0 大小的10倍,而L2则是L0的100倍。当L1被填满时L2就会开始被填入。由于每个级别没有重复数据,所以一个读操作可以在查找少数SSTable的情况下高效的完成。在许多读操作中,最多需要读取1~2个SSTable。事实上,90%的读只需要读取1个SSTable。最差的情况下是每个级别读取一个SSTable(由于每个SSTable增长10倍体积,所以Level不会很多)。使用这个策略进行压缩时候,需要的内存并不多,需要SSTable的10倍大小(50MB?)。过时的数据将会更快的被驱逐, 所以删除的数据只会占据SSTable很小的一部分。 不过,LCS的压缩方式出发的更频繁,占据节点上更多的I/O。 在写密集的的负载环境中,使用这种策略的收益不足以弥补I/O操作带来的性能损失。在Cassandra 2.2 或者更高的版本中,当启动一台新的LCS节点时候,旁路压缩操作的优化已经被实施。原始数据被直接移动到正确的级别,因为之前没有任何数据。performance improvements have been implemented that bypass compaction operations when bootstrapping a new node using LCS into a cluster. The original data is directly moved to the correct level because there is no existing data, so no partition overlap per level is present. For more information, see Apache Cassandra 2.2 - Bootstrapping Performance Improvements for Leveled Compaction.

有关LCS的更多介绍:http://www.datastax.com/dev/blog/leveled-compaction-in-apache-cassandra

DateTieredCompactionStrategy (DTCS)

  • Cassandra 2.0以后的版本才支持这个压缩方式
  • 推荐使用在时间序列和需要生存时间管理的负载环境
  • 优势:专为时间序列设计
  • 劣势:非顺序插入的数据会导致错误。在DTCS的情况下,读修复必须关闭

DTCS和STCS很像,但是它不是基于SSTable的大小进行压缩的,DTCS通过判断SSTable的年龄(创建时间)进行压缩。可配置的时间窗口确保新旧数据不会被混淆的合并到同一个SSTable。事实上,使用TTL时间戳,DTCS经常将包含过期数据的整个SSTable逐出。如果时间序列的输出是稳定的,这个策略也会导致许多大小相似的SSTable。通过配置时间周期,SSTable会在一个确切的时间进行合并。如果一些SSTable 正好落在相同的时间区间内,SSTable仍然会合并为更大的table,就像STCS一样。另外,如果SSTable达到了配置的年龄将不会进行压缩,减少数据重复写入的次数。使用这种策略压缩的SSTable可以高效的读取"last hour's worth of data",非常快。有个问题就是这种策略导致过期数据不容易写入,比如一条记录要写入过期的时间。读修复容易导致插入过期数据,所以需要关闭读取修复。
For more information about compaction strategies, see When to Use Leveled Compaction and Leveled Compaction in Apache Cassandra. For DateTieredCompactionStrategy, see Date-Tiered Compaction in Cassandra or DateTieredCompactionStrategy: Compaction for Time Series Data.

更多关于DTCS http://www.datastax.com/dev/blog/datetieredcompactionstrategy
DTCS 的测试 http://jimplush.com/talk/2015/02/03/cassandras-datetieredcompaction-strategy-works-as-billed/

译一篇有关DTCS的问题的的文章

作者开发了TWCS以规避DTCS的部分问题,但是并没有全部被官方认同,不过正好帮助我认识DTCS的局限性

https://issues.apache.org/jira/browse/CASSANDRA-9666

DTCS 非常适合时序数据,但它的注意事项,使其难以在生产中的应用(一些典型的操作:bootstrap,removenode,repair 在max_sstable_age_days后不再合并,hints/read repair破坏了选择算法)(译:不知道指的是什么选择算法)。

我提出一种替代方案,TimeWindowCompactionStrategy,它牺牲了DTCS的分层特性来弥补DTCS在操作上的一些缺陷。我相信有必要提出一种替代方案而不是调整DTCS,因为他基本上移除了分层特性以便移除max_sstable_age_days - 结果有很大不同,即使大量的参考了DTCS。

特别的,比起为增长的体积创建许多窗口(译注:一个时间段),这个策略允许选择窗口的大小,使用STCS压缩第一个窗口,在这个窗口不是当前窗口的情况下,进一步将数据向下压缩成一个SSTABLE。窗口的大小是一个混合的单位(分钟,小时,天)和大小。这样操作者可以认为所有的在窗口中的数据都压缩在一起(比如你有个一个6小时的窗口,你每天会有4个sstable,每个SSTABLE 保存了大约6小时数据)

这个结果解决了许多DTCS的问题:

  1. 目前,DTCS的第一个窗口是按照一个选定的规则压缩的,偏爱创建时间更早的文件,但是忽略体积。在TWCS(原文作者自己编写的一个策略)中,第一个窗口数据将由更加成熟、快速的压缩方案STCS。所有的的STCS选项都可以用于TWCS配置第一个窗口的压缩行为。

HintedHandoff 可能导致旧数据被放到新的sstable,会导致轻微的性能损失(sstable将会覆盖一个很大的范围,但是旧的时间戳不会在压缩的时候影响sstable的选择标准)

ReadRepair 可能导致旧数据被放到新的sstable,会导致轻微的性能损失(sstable将会覆盖一个很大的范围,但是旧的时间戳不会在压缩的时候影响sstable的选择标准)

Small, old sstables resulting from streams of any kind will be swiftly and aggressively compacted with the other sstables matching their similar maxTimestamp, without causing sstables in neighboring windows to grow in size.

The configuration options are explicit and straightforward - the tuning parameters leave little room for error. The window is set in common, easily understandable terms such as “12 hours”, “1 Day”, “30 days”. The minute/hour/day options are granular enough for users keeping data for hours, and users keeping data for years.

There is no explicitly configurable max sstable age, though sstables will naturally stop compacting once new data is written in that window.

Streaming operations can create sstables with old timestamps, and they'll naturally be joined together with sstables in the same time bucket. This is true for bootstrap/repair/sstableloader/removenode.

It remains true that if old data and new data is written into the memtable at the same time, the resulting sstables will be treated as if they were new sstables, however, that no longer negatively impacts the compaction strategy’s selection criteria for older windows.

如何修改压缩策略

创建的时候:

    CREATE TABLE use_view  (
    uid bigint PRIMARY KEY,
    ids map<int, int>
    ) WITH compaction = { 'class': 'org.apache.cassandra.db.compaction.LeveledCompactionStrategy'}

修改某个表的压缩策略:

    alter table use_view WITH compaction = { 'class': 'org.apache.cassandra.db.compaction.LeveledCompactionStrategy'}
posted @ 2015-08-13 22:06  wang#  阅读(4782)  评论(0编辑  收藏  举报