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

為了能夠理解讀寫的流程,必須要了解如下兩個(gè)概念:

1.The hinted handoff 特性?

2.Cassandra 對(duì) ACID 數(shù)據(jù)庫特性的哪些是滿足 哪些不滿足

在Cassandra中,一致性 consistency 表示的是一行數(shù)據(jù)如何更新并同步到所有的副本上。

How is data written?

Cassandra 的 write 分如下幾個(gè)階段:

Logging data in the commit log

Writing data to the memtable

Flushing data from the memtable

Storing data on disk in SSTables


寫Log及memtable

當(dāng)一個(gè)寫發(fā)生的時(shí)候,Cassandra將數(shù)據(jù)存儲(chǔ)在一個(gè)內(nèi)存結(jié)構(gòu)中,叫memtable, 同時(shí)為了持久化,也追加寫操作到磁盤上的commit log中。commit log記載了每一個(gè)到Cassandra 節(jié)點(diǎn)的寫入,這樣即使某個(gè)節(jié)點(diǎn)dang了,這些持久化的寫入log也不會(huì)丟。memtable是一個(gè) write-back Cache。Cassandra可以通過key在memtable中查找數(shù)據(jù)。memtables按照一定的順序來存儲(chǔ)寫入的數(shù)據(jù),當(dāng)寫入達(dá)到配置的大小限制時(shí),就將其flushed到磁盤上.

從memtable中Flushing數(shù)據(jù)

Cassandra以memtable中排好的順序?qū)?shù)據(jù)寫入到磁盤。同時(shí)也會(huì)在磁盤上創(chuàng)建一個(gè)?partition index,存放的是數(shù)據(jù)的token到磁盤位置的映射(也就是這個(gè)分片在磁盤中的位置,即索引)。當(dāng)memtable 的空間超過了配置的閾值(memtable_cleanup_threshold)或者commit log的空間超過了閾值,memtable 會(huì)被放入到一個(gè)隊(duì)列中,然后flush到磁盤。這個(gè)隊(duì)列的大小也是可配置的。如果待flush的數(shù)據(jù)超過了memtable_cleanup_threshold,Cassandra會(huì)block住寫操作。直到下一次flush成功。你可以手動(dòng)的flush一張表。為了減少 commit log的replay時(shí)間,最好在重啟節(jié)點(diǎn)之前,flush memtable。因?yàn)槿绻粋€(gè)節(jié)點(diǎn)掛了,重啟的時(shí)候需要replay commit log,把之前的寫入恢復(fù)到memtable中。

當(dāng)數(shù)據(jù)從memtable flush到磁盤的一個(gè)SSTable后,對(duì)應(yīng)的commit log數(shù)據(jù)將會(huì)被清除。

將數(shù)據(jù)存儲(chǔ)到磁盤中的SSTables中

每張表都有自己的Memtables 和 SSTables。而commit log則是表之間共用的。SSTables是不可改變的,當(dāng)memtable flushed成一個(gè)SSTable后,該SSTable就不能再寫東西進(jìn)去了。因此,一個(gè)partition存儲(chǔ)著多個(gè)SSTable文件。


對(duì)于每個(gè)SSTable,都有如下其他結(jié)構(gòu)輔助:

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是存儲(chǔ)在磁盤中的文件。從Cassandra 2.2后,SSTable文件的命名規(guī)則改為了縮文件路徑。數(shù)據(jù)文件存放在一個(gè)數(shù)據(jù)目錄中。對(duì)于每一個(gè)keyspace,一個(gè)目錄的下面的一個(gè)數(shù)據(jù)目錄存儲(chǔ)著一張表。例如?/data/data/ks1/cf1-5be396077b811e3a3ab9dc4b9ac088d/la-1-big-Data.db?代表著一個(gè)數(shù)據(jù)文件.其中ks1 代表keyspace的名字。一個(gè)全局唯一的十六進(jìn)制的字符串 5be396077b811e3a3ab9dc4b9ac088d 代表table ID。

Cassandra為每張表創(chuàng)建了子目錄,因此可以把table symlink到一個(gè)物理驅(qū)動(dòng)或者數(shù)據(jù)磁盤中。這樣可以將非?;钴S的表移動(dòng)到更快的媒介中,比如SSDs, 來獲得更好的性能;同時(shí)也將表拆分到各個(gè)掛載的存儲(chǔ)設(shè)備中,在存儲(chǔ)層獲得更好的I/O平衡。

How is data maintained?

在寫入過程中,將數(shù)據(jù)存入到SSTables中,SSTables 是不可更改的。在寫入或者更新時(shí),不是去覆蓋已有的行,而是寫入一個(gè)帶有新的時(shí)間戳版本的數(shù)據(jù)到新的SSTables中。在刪除操作時(shí),不是去(物理上)remove 需要?jiǎng)h的數(shù)據(jù),而是將它標(biāo)記為tombstones.

隨著時(shí)間的推移,Cassandra可能會(huì)在不同的SSTables中寫入一行的多個(gè)版本的數(shù)據(jù)。每個(gè)版本都可能有獨(dú)立的不同的時(shí)間戳的列集合。隨著SSTables的增加,數(shù)據(jù)的分布需要收集越來越多的SSTables來返回完整的一行數(shù)據(jù)。

為了保證數(shù)據(jù)庫的健康性,Cassandra周期性的合并SSTables,并將老數(shù)據(jù)廢棄掉。這個(gè)過程稱之為compaction。

compaction

Compaction是對(duì)一組SSTables進(jìn)行處理,它會(huì)收集每一行的所有列的所有version的,然后每一列都用(時(shí)間戳)最新的那一個(gè)version,把他們組成為完整的一行。這個(gè)merge的過程性能不錯(cuò),因此在每個(gè)SSTable中,數(shù)據(jù)是按?partition key?順序排好的,因此沒有隨機(jī)IO。重新組成的行將會(huì)被寫到新的SSTable中。


Compaction的過程中,由于新老SSTable同時(shí)存在,會(huì)有暫時(shí)的磁盤使用量和磁盤IO 上漲,當(dāng)Compaction完成后,老的SSTables將會(huì)被清除,從而把磁盤空間釋放出來。Compaction 的過程,會(huì)用新的SSTables替換多個(gè)老的SSTables,因此使讀性能大大提高。即使compaction還沒有完成,Cassandra也可以直接從新的SSTable中讀數(shù)據(jù),不用等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,這個(gè)決定了哪些SSTables被選中,以及compact的行在新的SSTables中如何排序。每一種策略都有自己的優(yōu)勢(shì)。

SizeTieredCompactionStrategy(STCS)

建議用在寫占比高的情況。

當(dāng)Cassandra 相同大小的SSTables數(shù)目達(dá)到一個(gè)固定的數(shù)目(默認(rèn)是4),STCS 開始?jí)嚎s。STCS將這些SSTables合并成一個(gè)大的SSTable。當(dāng)這些大的SSTable數(shù)量增加,STCS將它們合并成更大的SSTables。下圖給出了某一個(gè)時(shí)刻,各個(gè)SSTables的大?。海v坐標(biāo)為大小,每一個(gè)柱代表一個(gè)SSTable)。(相同大小的SSTable不超過3個(gè),因?yàn)?個(gè)就會(huì)被merge成更大的)

STCS 在寫占比高的情況下壓縮效果比較好,但讀變得更慢了,因?yàn)楦鶕?jù)大小來合并的過程不會(huì)將數(shù)據(jù)按行進(jìn)行分組,這樣使得某個(gè)特定行的多個(gè)版本更有可能分布在多個(gè)SSTables中。而且,STCS不會(huì)預(yù)期的回收刪除的數(shù)據(jù),因?yàn)閏ompaction的觸發(fā)條件是SSTable的大小,SSTables可能增長(zhǎng)的不夠快去合并和回收老數(shù)據(jù)。隨著最大的SSTables 大小在增加,disk需要同時(shí)存儲(chǔ)老的SSTables和新的SSTables。因此,在STCS壓縮的過程中,disk的磁盤使用量可能會(huì)超過該磁盤的quota。

優(yōu)勢(shì):?寫占比高的情況壓縮很好

劣勢(shì):?可能將過期的數(shù)據(jù)保存的很久,隨著時(shí)間推移,需要更多的存儲(chǔ)空間。

LeveledCompactionStrategy(LCS)

建議用在讀占比高的情況。

LCS減少了STCS多操作的一些問題。LCS策略是按level來compact的。首先,memtables中數(shù)據(jù)被flush到SSTables是第一層(L0)。LCS 壓縮將L0的SSTables 和L1 的SSTables 一起合并(成更大的 L1 SSTables,并且保證L1的SSTables的 key range 不重疊) 。

高于L1層的SSTables會(huì)被合并到一個(gè)大小大于等于sstable_size_in_md(默認(rèn)值:160MB)的SSTables中。如果一個(gè)L1層的SSTable存儲(chǔ)的數(shù)據(jù)大于L2( ??),LCS會(huì)將L2層的SSTable移動(dòng)到一個(gè)更高的level。

在每個(gè)高于L0層的等級(jí)中,LCS創(chuàng)建相同大小的SSTables。每一層的SSTable個(gè)數(shù)最多是上一層的10倍,因此L1層的SSTable是L0層的10倍,L2層是L0層100倍。如果compaction 后, 使L1層的SSTable個(gè)數(shù)超過了10個(gè),L1超出的SSTables就會(huì)被移到L2層。(??為啥是10個(gè)? 這里是設(shè)置了L0 最多一個(gè)SSTable是嗎?)

LCS壓縮過程確保了從L1層開始的SSTables不會(huì)有重復(fù)的數(shù)據(jù)。大部分的讀請(qǐng)求都能從一個(gè)或二個(gè)SSTables中獲取到需要的數(shù)據(jù)。實(shí)際上,90%的讀請(qǐng)求都能從一個(gè)SSTable中獲取到需要的數(shù)據(jù)。但L0 的SSTables 是沒有compact過的(直接從memtable dump的,所以key range 有overlap) ,所以,對(duì)于資源密集型的讀操作,還是可能會(huì)需要讀多個(gè)L0 SSTables。

高于L0層,LCS需要更少的磁盤空間去做壓縮,需要的磁盤空間一般是SSTable大小的10倍。過時(shí)的數(shù)據(jù)回收的更頻繁,因此已刪除的數(shù)據(jù)占用更少的磁盤空間。然而,LCS 的compaction 操作更頻繁,增加了節(jié)點(diǎn)的I/O負(fù)擔(dān)。對(duì)于寫占比高的情況,I/O操作會(huì)對(duì)性能造成巨大損失。測(cè)試表明,配置成LCS 策略的表的I/O都是打滿的。

注:當(dāng)使用LCS策略bootstrapping一個(gè)新節(jié)點(diǎn)到集群中時(shí),Cassandra會(huì)繞過compaction操作。初始的數(shù)據(jù)被直接搬到正確的層級(jí),因?yàn)閯倖?dòng)的node,每個(gè)level的數(shù)據(jù)都是空的,因此每一層沒有分片overlap。

優(yōu)勢(shì):?需要的磁盤空間小。讀延遲更短。過時(shí)的數(shù)據(jù)能夠及時(shí)回收。

劣勢(shì):? ? I/O使用率打太高,影響寫入延遲。


TimeWindowCompactionStrategy(TWCS)

建議用在時(shí)序且設(shè)置了TTL的情況。

TWCS有點(diǎn)類似于簡(jiǎn)化版的DTCS。TWCS按照時(shí)間窗口將SSTables分組。在compaction時(shí),TWCS在最近的時(shí)間窗口內(nèi)使用STCS去壓縮SSTables。當(dāng)一個(gè)時(shí)間窗口結(jié)束時(shí),TWCS將這個(gè)時(shí)間窗口的所有的SSTables壓縮成一個(gè)單獨(dú)的SSTable(基于SSTable 的 maximum timestamp ??)。一旦此時(shí)間窗口的major 壓縮(應(yīng)該是指這個(gè)最終的SSTable生成了)完成了,這部分?jǐn)?shù)據(jù)就不會(huì)再有進(jìn)一步的壓縮了。這個(gè)時(shí)間窗口結(jié)束之后,SSTable開始寫入下一個(gè)時(shí)間窗口。

如上圖所示,從上午10點(diǎn)到上午11點(diǎn),memtables flush到100MB的SSTables中。使用STCS策略將這些SSTables壓縮到更大的SSTables中。在上午11點(diǎn)的時(shí)候,這些SSTables被合并到一個(gè)單獨(dú)的SSTable,而且不會(huì)被TWCS再進(jìn)行壓縮了。11點(diǎn)到12點(diǎn)之間創(chuàng)建的新的SSTables使用STCS進(jìn)行壓縮,在這個(gè)時(shí)間窗口結(jié)束的時(shí)候,又把這些SSTables合并到一個(gè)單獨(dú)的SSTable,然后開始新一輪的TWCS壓縮。注意,每個(gè)TWCS時(shí)間窗口數(shù)據(jù)量是不同的。

TWCS有兩個(gè)主要的參數(shù):

compaction_window_unit:?時(shí)間單位,用來定義窗口大小(milliseconds,seconds,hours等等)

compaction_window_size:?每個(gè)窗口有多少單元(1,2,3等等)

上面那個(gè)例子中:compaction_window_unit = ‘minutes’,compaction_window_size = 60

優(yōu)勢(shì):用于時(shí)間序列數(shù)據(jù),為表中所有數(shù)據(jù)使用默認(rèn)的TTL。比DTCS配置更簡(jiǎn)單。

劣勢(shì):?不適用于時(shí)間亂序的數(shù)據(jù),因?yàn)镾STables沒法壓縮;也不適用于沒有設(shè)置TTL的數(shù)據(jù),因?yàn)槿萘繒?huì)不斷增長(zhǎng);相比較DTCS,能夠配置的參數(shù)更少。

DateTieredCompactionStrategy(DTCS)

Cassandra 3.0.8/3.8 中棄用了。

DTCS于STCS類似。但是STCS壓縮是基于SSTable的 大小,而DTCS是基于SSTable的年紀(jì)(age)。在一個(gè)SSTable中,每一列都標(biāo)記著一個(gè)寫入的時(shí)間戳。DTCS使用SSTable所有列中oldest(最小的)時(shí)間戳作為SSTable的年紀(jì)。

。。。

哪一種壓縮策略最好

為了實(shí)現(xiàn)最好的壓縮策略:

1. Review 你應(yīng)用的需求

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

3. 測(cè)試壓縮策略

可以根據(jù)以下問題來選擇策略:

你的表處理的是時(shí)間序列的數(shù)據(jù)嗎?

如果是的,你最好的選擇是TWCS 或者DTCS。

如果你的表不是局限于時(shí)間序列的數(shù)據(jù),選擇就變得更加復(fù)雜了。下面的問題可能會(huì)給你其他的考慮去做選擇。

你的表處理讀比寫多,或者寫多于讀嗎?

如果表處理的讀是寫的兩倍及以上——尤其是隨機(jī)讀,LCS 是一個(gè)好的選擇。如果讀寫一比一,那么LCS會(huì)對(duì)性能有影響(IO),優(yōu)勢(shì)不明顯。大批量的寫入會(huì)很容易把LCS搞崩(IO打滿)。

表中的數(shù)據(jù)是否經(jīng)常改變?

LCS的一個(gè)優(yōu)勢(shì)在于它將相關(guān)的數(shù)據(jù)都保持在小范圍的SSTables中。但如果你的數(shù)據(jù)是不可更改的或者不是經(jīng)常做upserts,那么STCS可以實(shí)現(xiàn)相同類型的分組,并且性能不會(huì)收到影響(但LCS會(huì))。

Do you require predictable levels of read and write activity?

LCS 保證SSTables在一個(gè)可預(yù)測(cè)的大小和數(shù)量中。例如,如果你的表讀/寫比例比較?。磳懚嘧x少),為了滿足讀的SLA,犧牲寫性能,去確保讀的速率和延遲在一個(gè)可預(yù)測(cè)的等級(jí)。并且可以通過水平擴(kuò)展(添加更多的節(jié)點(diǎn))來彌補(bǔ)犧牲的寫性能。

表會(huì)使用batch操作嗎?

batch寫或batch讀,STCS表現(xiàn)的都比LCS好。batch過程造成幾乎不會(huì)產(chǎn)生碎片,因此LCS的好處體現(xiàn)不出來,batch操作可以把配置為L(zhǎng)CS策略的表搞崩的。

系統(tǒng)有受限的磁盤空間嗎?

LCS處理磁盤空間比STCS更高效:LCS除了數(shù)據(jù)本身占用的空間,需要大約10%的預(yù)留空間。STCS和DTCS需要更多,在某些情況下,差不多需要50%。

系統(tǒng)是否到達(dá)I/O限制

LCS相比較DTCS 或者STCS,對(duì)I/O更加的敏感。換成LCS,會(huì)引入更多的I/O,使LCS的優(yōu)勢(shì)被削弱了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容