Database internals - write + maitain

https://docs.datastax.com/en/cassandra-oss/3.0/cassandra/dml/dmlHowDataMaintain.html

https://blog.csdn.net/FS1360472174/article/details/55005335

为了能够理解读写的流程,必须要了解如下两个概念:

1.The hinted handoff 特性 

2.Cassandra 对 ACID 数据库特性的哪些是满足 哪些不满足

在Cassandra中,一致性 consistency 表示的是一行数据如何更新并同步到所有的副本上。

How is data written?

Cassandra 的 write 分如下几个阶段:

Logging data in the commit log

Writing data to the memtable

Flushing data from the memtable

Storing data on disk in SSTables


写Log及memtable

当一个写发生的时候,Cassandra将数据存储在一个内存结构中,叫memtable, 同时为了持久化,也追加写操作到磁盘上的commit log中。commit log记载了每一个到Cassandra 节点的写入,这样即使某个节点dang了,这些持久化的写入log也不会丢。memtable是一个 write-back Cache。Cassandra可以通过key在memtable中查找数据。memtables按照一定的顺序来存储写入的数据,当写入达到配置的大小限制时,就将其flushed到磁盘上.

从memtable中Flushing数据

Cassandra以memtable中排好的顺序将数据写入到磁盘。同时也会在磁盘上创建一个 partition index,存放的是数据的token到磁盘位置的映射(也就是这个分片在磁盘中的位置,即索引)。当memtable 的空间超过了配置的阈值(memtable_cleanup_threshold)或者commit log的空间超过了阈值,memtable 会被放入到一个队列中,然后flush到磁盘。这个队列的大小也是可配置的。如果待flush的数据超过了memtable_cleanup_threshold,Cassandra会block住写操作。直到下一次flush成功。你可以手动的flush一张表。为了减少 commit log的replay时间,最好在重启节点之前,flush memtable。因为如果一个节点挂了,重启的时候需要replay commit log,把之前的写入恢复到memtable中。

当数据从memtable flush到磁盘的一个SSTable后,对应的commit log数据将会被清除。

将数据存储到磁盘中的SSTables中

每张表都有自己的Memtables 和 SSTables。而commit log则是表之间共用的。SSTables是不可改变的,当memtable flushed成一个SSTable后,该SSTable就不能再写东西进去了。因此,一个partition存储着多个SSTable文件。


对于每个SSTable,都有如下其他结构辅助:

Data (Data.db)

The SSTable data

Primary Index (Index.db)

Index of the row keys with pointers to their positions in the data file

Bloom filter (Filter.db)

A structure stored in memory that checks if row data exists in the memtable before accessing SSTables on disk

Compression Information (CompressionInfo.db)

A file holding information about uncompressed data length, chunk offsets and other compression information

Statistics (Statistics.db)

Statistical metadata about the content of the SSTable

Digest (Digest.crc32, Digest.adler32, Digest.sha1)

A file holding adler32 checksum of the data file

CRC (CRC.db)

A file holding the CRC32 for chunks in an uncompressed file.

SSTable Index Summary (SUMMARY.db)

A sample of the partition index stored in memory

SSTable Table of Contents (TOC.txt)

A file that stores the list of all components for the SSTable TOC

Secondary Index (SI_.*.db)

Built-in secondary index. Multiple SIs may exist per SSTable

SSTables是存储在磁盘中的文件。从Cassandra 2.2后,SSTable文件的命名规则改为了缩文件路径。数据文件存放在一个数据目录中。对于每一个keyspace,一个目录的下面的一个数据目录存储着一张表。例如 /data/data/ks1/cf1-5be396077b811e3a3ab9dc4b9ac088d/la-1-big-Data.db 代表着一个数据文件.其中ks1 代表keyspace的名字。一个全局唯一的十六进制的字符串 5be396077b811e3a3ab9dc4b9ac088d 代表table ID。

Cassandra为每张表创建了子目录,因此可以把table symlink到一个物理驱动或者数据磁盘中。这样可以将非常活跃的表移动到更快的媒介中,比如SSDs, 来获得更好的性能;同时也将表拆分到各个挂载的存储设备中,在存储层获得更好的I/O平衡。

How is data maintained?

在写入过程中,将数据存入到SSTables中,SSTables 是不可更改的。在写入或者更新时,不是去覆盖已有的行,而是写入一个带有新的时间戳版本的数据到新的SSTables中。在删除操作时,不是去(物理上)remove 需要删的数据,而是将它标记为tombstones.

随着时间的推移,Cassandra可能会在不同的SSTables中写入一行的多个版本的数据。每个版本都可能有独立的不同的时间戳的列集合。随着SSTables的增加,数据的分布需要收集越来越多的SSTables来返回完整的一行数据。

为了保证数据库的健康性,Cassandra周期性的合并SSTables,并将老数据废弃掉。这个过程称之为compaction。

compaction

Compaction是对一组SSTables进行处理,它会收集每一行的所有列的所有version的,然后每一列都用(时间戳)最新的那一个version,把他们组成为完整的一行。这个merge的过程性能不错,因此在每个SSTable中,数据是按 partition key 顺序排好的,因此没有随机IO。重新组成的行将会被写到新的SSTable中。


Compaction的过程中,由于新老SSTable同时存在,会有暂时的磁盘使用量和磁盘IO 上涨,当Compaction完成后,老的SSTables将会被清除,从而把磁盘空间释放出来。Compaction 的过程,会用新的SSTables替换多个老的SSTables,因此使读性能大大提高。即使compaction还没有完成,Cassandra也可以直接从新的SSTable中读数据,不用等compaction完成。

As Cassandra processes writes and reads, it replaces the old SSTables with new SSTables in the page cache. The process of caching the new SSTable, while directing reads away from the old one, is incremental — it does not cause a the dramatic cache miss. Cassandra provides predictable high performance even under heavy load.


Compaction strategies

Cassandra 支持不同类型的compaction,这个决定了哪些SSTables被选中,以及compact的行在新的SSTables中如何排序。每一种策略都有自己的优势。

SizeTieredCompactionStrategy(STCS)

建议用在写占比高的情况。

当Cassandra 相同大小的SSTables数目达到一个固定的数目(默认是4),STCS 开始压缩。STCS将这些SSTables合并成一个大的SSTable。当这些大的SSTable数量增加,STCS将它们合并成更大的SSTables。下图给出了某一个时刻,各个SSTables的大小:(纵坐标为大小,每一个柱代表一个SSTable)。(相同大小的SSTable不超过3个,因为4个就会被merge成更大的)

STCS 在写占比高的情况下压缩效果比较好,但读变得更慢了,因为根据大小来合并的过程不会将数据按行进行分组,这样使得某个特定行的多个版本更有可能分布在多个SSTables中。而且,STCS不会预期的回收删除的数据,因为compaction的触发条件是SSTable的大小,SSTables可能增长的不够快去合并和回收老数据。随着最大的SSTables 大小在增加,disk需要同时存储老的SSTables和新的SSTables。因此,在STCS压缩的过程中,disk的磁盘使用量可能会超过该磁盘的quota。

优势: 写占比高的情况压缩很好

劣势: 可能将过期的数据保存的很久,随着时间推移,需要更多的存储空间。

LeveledCompactionStrategy(LCS)

建议用在读占比高的情况。

LCS减少了STCS多操作的一些问题。LCS策略是按level来compact的。首先,memtables中数据被flush到SSTables是第一层(L0)。LCS 压缩将L0的SSTables 和L1 的SSTables 一起合并(成更大的 L1 SSTables,并且保证L1的SSTables的 key range 不重叠) 。

高于L1层的SSTables会被合并到一个大小大于等于sstable_size_in_md(默认值:160MB)的SSTables中。如果一个L1层的SSTable存储的数据大于L2( ??),LCS会将L2层的SSTable移动到一个更高的level。

在每个高于L0层的等级中,LCS创建相同大小的SSTables。每一层的SSTable个数最多是上一层的10倍,因此L1层的SSTable是L0层的10倍,L2层是L0层100倍。如果compaction 后, 使L1层的SSTable个数超过了10个,L1超出的SSTables就会被移到L2层。(??为啥是10个? 这里是设置了L0 最多一个SSTable是吗?)

LCS压缩过程确保了从L1层开始的SSTables不会有重复的数据。大部分的读请求都能从一个或二个SSTables中获取到需要的数据。实际上,90%的读请求都能从一个SSTable中获取到需要的数据。但L0 的SSTables 是没有compact过的(直接从memtable dump的,所以key range 有overlap) ,所以,对于资源密集型的读操作,还是可能会需要读多个L0 SSTables。

高于L0层,LCS需要更少的磁盘空间去做压缩,需要的磁盘空间一般是SSTable大小的10倍。过时的数据回收的更频繁,因此已删除的数据占用更少的磁盘空间。然而,LCS 的compaction 操作更频繁,增加了节点的I/O负担。对于写占比高的情况,I/O操作会对性能造成巨大损失。测试表明,配置成LCS 策略的表的I/O都是打满的。

注:当使用LCS策略bootstrapping一个新节点到集群中时,Cassandra会绕过compaction操作。初始的数据被直接搬到正确的层级,因为刚启动的node,每个level的数据都是空的,因此每一层没有分片overlap。

优势: 需要的磁盘空间小。读延迟更短。过时的数据能够及时回收。

劣势:    I/O使用率打太高,影响写入延迟。


TimeWindowCompactionStrategy(TWCS)

建议用在时序且设置了TTL的情况。

TWCS有点类似于简化版的DTCS。TWCS按照时间窗口将SSTables分组。在compaction时,TWCS在最近的时间窗口内使用STCS去压缩SSTables。当一个时间窗口结束时,TWCS将这个时间窗口的所有的SSTables压缩成一个单独的SSTable(基于SSTable 的 maximum timestamp ??)。一旦此时间窗口的major 压缩(应该是指这个最终的SSTable生成了)完成了,这部分数据就不会再有进一步的压缩了。这个时间窗口结束之后,SSTable开始写入下一个时间窗口。

如上图所示,从上午10点到上午11点,memtables flush到100MB的SSTables中。使用STCS策略将这些SSTables压缩到更大的SSTables中。在上午11点的时候,这些SSTables被合并到一个单独的SSTable,而且不会被TWCS再进行压缩了。11点到12点之间创建的新的SSTables使用STCS进行压缩,在这个时间窗口结束的时候,又把这些SSTables合并到一个单独的SSTable,然后开始新一轮的TWCS压缩。注意,每个TWCS时间窗口数据量是不同的。

TWCS有两个主要的参数:

compaction_window_unit: 时间单位,用来定义窗口大小(milliseconds,seconds,hours等等)

compaction_window_size: 每个窗口有多少单元(1,2,3等等)

上面那个例子中:compaction_window_unit = ‘minutes’,compaction_window_size = 60

优势:用于时间序列数据,为表中所有数据使用默认的TTL。比DTCS配置更简单。

劣势: 不适用于时间乱序的数据,因为SSTables没法压缩;也不适用于没有设置TTL的数据,因为容量会不断增长;相比较DTCS,能够配置的参数更少。

DateTieredCompactionStrategy(DTCS)

Cassandra 3.0.8/3.8 中弃用了。

DTCS于STCS类似。但是STCS压缩是基于SSTable的 大小,而DTCS是基于SSTable的年纪(age)。在一个SSTable中,每一列都标记着一个写入的时间戳。DTCS使用SSTable所有列中oldest(最小的)时间戳作为SSTable的年纪。

。。。

哪一种压缩策略最好

为了实现最好的压缩策略:

1. Review 你应用的需求

2. 配置表使用最合适的策略

3. 测试压缩策略

可以根据以下问题来选择策略:

你的表处理的是时间序列的数据吗?

如果是的,你最好的选择是TWCS 或者DTCS。

如果你的表不是局限于时间序列的数据,选择就变得更加复杂了。下面的问题可能会给你其他的考虑去做选择。

你的表处理读比写多,或者写多于读吗?

如果表处理的读是写的两倍及以上——尤其是随机读,LCS 是一个好的选择。如果读写一比一,那么LCS会对性能有影响(IO),优势不明显。大批量的写入会很容易把LCS搞崩(IO打满)。

表中的数据是否经常改变?

LCS的一个优势在于它将相关的数据都保持在小范围的SSTables中。但如果你的数据是不可更改的或者不是经常做upserts,那么STCS可以实现相同类型的分组,并且性能不会收到影响(但LCS会)。

Do you require predictable levels of read and write activity?

LCS 保证SSTables在一个可预测的大小和数量中。例如,如果你的表读/写比例比较小(即写多读少),为了满足读的SLA,牺牲写性能,去确保读的速率和延迟在一个可预测的等级。并且可以通过水平扩展(添加更多的节点)来弥补牺牲的写性能。

表会使用batch操作吗?

batch写或batch读,STCS表现的都比LCS好。batch过程造成几乎不会产生碎片,因此LCS的好处体现不出来,batch操作可以把配置为LCS策略的表搞崩的。

系统有受限的磁盘空间吗?

LCS处理磁盘空间比STCS更高效:LCS除了数据本身占用的空间,需要大约10%的预留空间。STCS和DTCS需要更多,在某些情况下,差不多需要50%。

系统是否到达I/O限制

LCS相比较DTCS 或者STCS,对I/O更加的敏感。换成LCS,会引入更多的I/O,使LCS的优势被削弱了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,417评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,921评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,850评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,945评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,069评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,188评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,239评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,994评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,409评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,735评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,898评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,578评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,205评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,916评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,156评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,722评论 2 363
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,781评论 2 351