暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

技术基础 | 模式配置的调优:压实策略、MemTable的刷盘操作

DataStax 2021-02-01
690

点击蓝字 关注我们



本文为DataStax Enterprise (DSE)和Apache Cassandra™提供了调优建议,阅读本文需具备DSE/Cassandra的基础知识。它并不能替代官方文档。


就如数据模型和模式(schema)配置检查中提到的,数据建模是项目成败与否的关键之一。此外,Cassandra和DSE的性能会受到模式配置的影响。


Cassandra和DataStax Enterprise允许您制定每个表的参数,如压实策略、数据压缩算法等等。本文档介绍了经常会被调整的配置参数,并提供了相关的调优建议。





压实策略

在深入研究压实策略之前,让我们先回顾一下数据是如何被写入到磁盘的。

如上图所示,从最初的立即将被写入的数据记录到commit log到最终的将数据写入硬盘,Cassandra的写入路径有多个步骤:

  1. 将数据写入commit log。

  2. 把数据写入memtable。

  3. Flush memtable中的数据——此步骤由特定条件触发,并可通过cassandra.yaml中的多个参数进行配置。

  4. 将数据储存在磁盘上的SSTable中。


SSTable是不可变的(immutable),储存在SSTable中的数据永远不会被就地更新或删除。相反,当执行新的写入操作时,对于数据的更新会先被写入一个新的memtable,继而被写入一个新的SSTable,而非直接改动已有的数据文件。


压实进程会在后台将多个SSTable进行合并。不然,读取路径涉及到越多的SSTable,读取的时延就会越久。理想情况下,一个数据库被合理调优后,一条查询语句不会涉及超过2~3个SSTable。


DSE提供了三个主要的压实策略,每个都有其特定的使用场景:

  1. STCS (Size Tiered Compaction Strategy):适用于读写混合的工作负载。

  2. LCS (Leveled compaction strategy):适用于大量读取的使用场景,因为这个策略减少了数据分布在多个SSTable的情况。

  3. TWCS (Time window compaction strategy):适用于时间序列类型或任何有TTL(存活时间)限制的数据库表


在对数据库表进行调优之前,这里有一份关于各个压实策略的利弊对比。


01

常见的压实配置参数

如果你看到很多等待处理的压实任务,那么你的系统可能需要调优。两个主要的压实参数分别是:

concurrent_compactors


执行压实任务的并行线程的数量。


要改变此参数,先从增加compaction_throughput_mb_per_sec开始,并且只有当你有足够的IO时再改变这项参数。STCS和TWCS会因这项参数的增加而受益,但LCS很多情况下最多只能使用两个压实线程。


compaction_throughput_mb_per_sec


压实操作处理数据的吞吐量(以MB/S为单位)。这是一项针对所有压实线程的吞吐量总和的限制,而不是针对某个单一的线程!


请注意:执行更多的压实操作会需要调用更多的资源,同时GC压力也会增加。


你可以使用任意你喜欢的监测解决方案或下面的两个操作指令来查询等待处理的压实任务。

nodetool sjk mx -f Value -mg -b org.apache.cassandra.metrics:type=Compaction,name=PendingTasks

nodetool compactionstats


请注意,由于以下配置参数,墓碑可以在常规压实策略之外触发压实操作:

tombstone_compaction_interval


针对一个单独的SSTable的压实操作会根据估算的墓碑比例而被触发。这个参数可以调整两次独个SSTable压实操作之间的间隔(默认值为1天)。


Unchecked_tombstone_compaction


只要估算的墓碑比例比tombstone_threshold的值高,Cassandra每天都会执行一次针对单个SSTable的压实操作(“一天”这个频率是tombstone_compaction_interval的默认值)。为了更快地移除墓碑,你可以降低这个值,但系统会消耗更多资源。


tombstone_threshold


可被垃圾收集(gc)的墓碑和所涉及到的表列的数量的比例。


接下来的部分按压实操作类型介绍了可使用的参数列表。请仅在你无法通过改变上述参数提高压实性能时,才考虑改变以下这些参数。



02

Size Tiered Compaction Strategy (STCS)

使用本压实策略时,当数据库看到足够多的大小相近、其值在[average_sze * bucket_low, average_sze * bucket_high]之间的表后,它便会将这些SSTable合并到一个文件中。


如下图所示,合并后的文件会随着时间变化越来越大:

在历经多次数据写入后的Size Tiered Compaction


STCS这种压实策略有多个可调优的参数,但通常只需要调整以下两个参数,并仅针对于特殊场景:

min_threshold


触发小型压实操作(minor compaction)最少需要的SSTable数量。


你可以通过调低这个参数以提高压实操作发生的可能性。不过这样会触发更多的压实任务,导致消耗更多的资源。


min_sstable_size


STCS将SSTable分组(bucket)。


分组过程会将大小差异不超过50%的SSTable分在同一组。不过对于过小的SSTable来说,这种分组方式会显得太过精细。


如果你的SSTable比较小,请使用min_sstable_size重新定义分组所依据的SSTable大小的阈值(该值以字节为单位),从而使得大小在新的阈值之下的SSTable都被分到同一组中。


最佳实践方式是将每张表的SSTable数量限制在15到25之间。如果你看到(使用STCS的数据库表)超过了25个SSTable,请调节相关配置以增加压实频率。



03

Leveled Compaction Strategy (LCS)

Leveled Compaction Strategy (LCS)这种压实策略构建了大小固定且相对较小的SSTable(其默认值为160MB),并将它们划分为多个级别(level)。每个级别中的SSTable确保不会互相有所重叠。


下图简易地展示了数据是如何跨level移动的:

Leveled Compaction - 添加SSTable的过程


LCS的配置参数包含了用于设置SSTable的目标大小的sstable_size_in_mb。


请注意:对于很大的分区,LCS这种压实算法不会将数据拆分成多个SStable。这样可以确保一个级别(level)中只有一个单独的SSTable。


L0可能会是一个混乱的空间,因此也请注意适当地调节所有memtable的参数。在大量读取的场景下,DataStax建议对memtable的flush频率要低于使用STCS压实策略时的频率。



04

Time Window Compaction Strategy

本压实策略自Cassandra 3.0以来代替了DTCS策略。对于所有有时间序列或TTL的数据的使用场景,它都是完美的选择。


其主要原理是通过定义一个压实的时间窗口从而将一个时间序列分组,并只对当前活跃的时间窗口使用STCS算法进行压实。


当这一时间窗口结束后,数据库会将这组中所有的文件压实成一个单独的文件。在时间窗口活跃期内,系统会以STCS策略执行压实操作,并且所有的STCS参数都适用。

Time Window Compaction Strategy的工作原理


除STCS的配置参数之外,TWCS还有以下的参数:

compaction_window_unit


定义窗口大小的时间单位(毫秒、秒、小时等)。


compaction_window_size


每个窗口的时间单位数(1、2、3以此类推)。


因为第一组使用的是STCS策略,为了更好的压实性能,最好将这个活跃窗口里的SSTable数量保持在20左右。此外,最好(借助TTL)将非活跃的窗口数控制在30个以下(最多50)。


请注意:你的使用场景可能会有所不同,所以可能适用不同的值。为确保性能不随时间推移而下降,请确保进行适当的大规模测试。


在此展示一个有关时间序列的使用场景:请设想一个需要将数据保存一年(TTL为365天)的IoT使用场景。根据前面的配置建议,压实操作的时间窗口大小应该为365/30 => ~ 12天(以“天(DAYS)”为单位)。


在此配置下,只有最近12天的数据会被压实,其他的数据则会保持不可变(immutable)的状态,这样便会减小压实所需要的开销对系统造成的影响。



Memtable的刷盘(flush)过程

通常情况下,Cassandra会在以下情况下将Memtable中的数据flush到磁盘:

  • 达到memtable的flush阈值时。

  • 系统关机时。

  • 执行nodetool flushnodetool drain命令时。

  • commit log已满时。


定期显性地执行memtable的flush也是可行的,这是由 memtable_flush_period_in_ms参数所控制。一般情况下,这个参数就保持其默认值0就好,这样memtable只会按前面所讲的规则进行flush。


建议只在特殊情况或针对特定数据库表调整此项参数,比如:有些数据库表在很长时间里几乎没有被改动过,所以你不想让与它们相关的commit log在磁盘中保留太久。


如果是这样,可以将这些数据库表的memtable设置为每天或每X小时将数据flush到磁盘上。请注意这个参数的单位为毫秒。



本文内容版权归DataStax所有

未经书面允许禁止转载


推荐阅读


DataStax在中国

技术资讯 | 行业动态 | 活动信息

阅读这篇文章有收获?
请通过点赞、分享和在看告诉我们

文章转载自DataStax,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论