cassandra 3.x官方文檔(7)---內部原理之如何讀寫數據

寫在前面html

cassandra3.x官方文檔的非官方翻譯。翻譯內容水平全依賴本人英文水平和對cassandra的理解。因此強烈建議閱讀英文版cassandra 3.x 官方文檔。此文檔一半是翻譯,一半是我的對cassandra的認知。儘可能將個人理解經過引用的方式標註,以示區別。另外文檔翻譯是項長期並有挑戰的工做,若是你願意加入cassandra git book,能夠發信給我。固然你也能夠加入咱們的QQ羣,104822562。一塊兒學習探討cassandra.node

如何寫

Cassandra寫的時候分好幾個階段寫處理數據,從當即寫一個write操做開始,到把數據寫到磁盤中git

  • 寫log到commit log數據庫

  • 寫數據到memtableapache

  • 從memtable中flush數據bootstrap

  • 將數據存儲在SSTables中的磁盤中緩存

寫Log及memtable存儲app

當一個寫發生的時候,Cassandra將數據存儲在一個內存結構中,叫memtable,而且提供了可配置分佈式

的持久化,同時也追加寫操做到磁盤上的commit log中。commit log記載了每個到Cassandra 節點的寫入。函數

這些持久化的寫入永久的存活即便某個節點掉電了。memtable是一個數據分區寫回的緩存。Cassandra經過key

來查找。memtables順序寫,直到達到配置的限制,而後flushed.

從memtable中Flushing數據

爲了flush數據,Cassandra以memtable-sorted的順序將數據寫入到磁盤。同時也會在磁盤上建立一個分區索引,

將數據的token map到磁盤的位置。當memtable 內容超過了配置的閾值或者commitlog的空間超過了

commitlog_total_space_in_mb的值,memtable 會被放入到一個隊列中,而後flush到磁盤中。這個隊列能夠經過

cassandra.yaml文件中memtable_heap_space_in_mb,或者memtable_offheap_space_in_mb來配置。若是待flush的

數據超過了memtable_cleanup_threshold,Cassandra會block住寫操做。直到下一次flush成功。你能夠手動的flush一張表,

使用nodetool flush 或者nodetool drain(flushes memtables 不須要監聽跟其餘節點的鏈接)。爲了下降commit log

的恢復時間,建議的最佳實踐是在從新啓動節點以前,flush memtable.若是一個節點中止了工做,將會從節點中止前開始,將commit log

恢復到memtable中。

當數據從memtable中flush到磁盤的一個SSTable中,對應的commit log數據將會被清除。

將數據存儲到磁盤中的SSTables中

Memtables 和 SSTables是根據每張表來維護的。而commit log則是表之間共用的。SSTables是不可改變的,當memtable被flushed後,

是不可以從新寫入的。所以,一個分區存儲着多個SSTable文件。有幾個其餘的SSTable 結構存在幫助讀操做。

對於每個SSTable,Cassandra 建立了這些結構:

Data(Data.db)

SSTable的數據

Primary Index(Index.db)

行index的指針,指向文件中的位置

Bloom filter (Filter.db)

一種存儲在內存中的結構,在訪問磁盤中的SSTable以前,檢查行數據是否存在memtable中

Compression Information(CompressionInfo.db)

保存未壓縮的數據長度,chunk的起點和其餘壓縮信息。

Statistics(Statistics.db)

SSTable的內容統計數據元數據。

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

保存adler32 checksum的數據文件

CRC (CRC.db)

保存沒有被壓縮的文件中的chunks的CRC32

SSTable Index Summary(SUMMARY.db)

存儲在內存中的的分區索引的一個樣例。

SSTable Table of Contents(TOC.txt)

存儲SSTable TOC 中全部的組件的列表。

Secondary Index(SL_.*.db)

內置的secondary index。每一個SSTable可能存在多個SIs中。

SSTables是存儲在磁盤中的文件。SSTable文件的命名從Cassandra 2.2開始後發生變化爲了

縮短文件路徑。變化發生在安裝的時候,數據文件存儲在一個數據目錄中。對於每個keyspace,

一個目錄的下面一個數據目錄存儲着一張表。例如,

/data/data/ks1/cf1-5be396077b811e3a3ab9dc4b9ac088d/la-1-big-Data.db 表明着

一個數據文件.ks1 表明着keyspace 名字爲了在streaming或者bulk loading數據的時候區分

keyspace。一個十六進制的字符串,5be396077b811e3a3ab9dc4b9ac088d在這個例子中,被加到

table名字中表明着unique的table IDs.

Cassandra爲每張表建立了子目錄,容許你能夠爲每一個table建立syslink,map到一個物理驅動或者數據

磁盤中。這樣能夠將很是活躍的表移動到更快的媒介中,好比SSDs,得到更好的性能,同時也將表拆分到各個

掛載的存儲設備中,在存儲層得到更好的I/O平衡。

數據是如何維護

Cassandra 寫入過程當中將數據存入到的文件叫作SSTables.SSTables 是不可更改的。Cassandra在寫入或者更新時不是去覆蓋已有的行,而是寫入一個帶有新的時間戳版本的數據到新的SSTables中。Cassandra刪除操做不是去移除數據,而是將它標記爲墓碑

隨着時間的推移,Cassandra可能會在不一樣的SSTables中寫入一行的多個版本的數據。每一個版本均可能有獨立的不一樣的時間戳的列集合。隨着SSTables的增長,數據的分佈須要收集愈來愈多的SSTables來返回一個完整的行數據。

爲了保證數據庫的健康性,Cassandra週期性的合併SSTables,並將老數據廢棄掉。這個過程稱之爲合併壓縮。

合併壓縮

Cassandra 支持不一樣類型的壓縮策略,這個決定了哪些SSTables被選中作compaction,以及壓縮的行在新的SSTables中如何排序。每一種策略都有本身的優點,下面的段落解釋了每一種Cassandra’s compaction 策略。

儘管下面片斷的開始都介紹了一個經常使用的推薦,可是有不少的影響因子使得compaction策略的選擇變得很複雜。

SizeTieredCompactionStrategy(STCS)

建議用在寫佔比高的狀況。 
當Cassandra 相同大小的SSTables數目達到一個固定的數目(默認是4),STCS 開始壓縮。STCS將這些SSTables合併成一個大的SSTable。當這些大的SSTable數量增長,STCS將它們合併成更大的SSTables。在給定的時間範圍內,SSTables大小變化以下圖所示 

STCS 在寫佔比高的狀況下壓縮效果比較好,它將讀變得慢了,由於根據大小來合併的過程不會將數據按行進行分組,這樣使得某個特定行的多個版本更有可能分佈在多個SSTables中。並且,STCS不會預期的回收刪除的數據,由於觸發壓縮的是SSTable的大小,SSTables可能增加的足夠快去合併和回收老數據。隨着最大的SSTables 大小在增長,disk須要空間同時去存儲老的SSTables和新的SSTables。在STCS壓縮的過程當中可能回超過一個節點上典型大小的磁盤大小。

  • 優點: 寫佔比高的狀況壓縮很好
  • 劣勢: 可能將過時的數據保存的好久,隨着時間推移,須要的內存大小隨之增長。

LeveledCompactionStrategy(LCS)

建議用在讀佔比高的狀況。

LCS減小了STCS多操做的一些問題。這種策略是經過一系列層級來工做的。首先,memtables中數據被flush到SSTables是第一層(L0)。LCS 壓縮將這些第一層的SSTables合併成更大的SSTables L1。

Leveled compaction —— 添加SSTables 

高於L1層的SSTables會被合併到一個大小大於等於sstable_size_in_md(默認值:160MB)的SSTables中。若是一個L1層的SSTable存儲的一部分數據大於L2,LCS會將L2層的SSTable移動到一個更高的等級。

許多插入操做以後的Leveled compaction 

在每一個高於L0層的等級中,LCS建立相同大小的SSTables。每一層大小是上一層的10倍,所以L1層的SSTable是L0層的10倍,L2層是L0層100倍。若是L1層的壓縮結果超過了10倍,超出的SSTables就會被移到L2層。

LCS壓縮過程確保了從L1層開始的SSTables不會有重複的數據。對於許多讀,這個過程是的Cassandra可以從一個或者二個SSTables中獲取到所有的數據。實際上,90%的都可以知足從一個SSTable中獲取。由於LCS不去compact L0 tables。資源敏感型的讀涉及到多個L0 SSTables的狀況仍是會發生。

高於L0層,LCS須要更少的磁盤空間去作壓縮——通常是SSTable大小的10倍。過期的數據回收的更頻繁,所以刪除的數據佔用磁盤空間更少的比例。然而,LCS 壓縮操做使用了更多的I/O操做,增長了節點的I/O負擔。對於寫佔比高的狀況,使用這種策略的獲取的報酬不值得付出的I/O操做對性能形成損失的代價。在大多數狀況下,配置成LCS的表的測試代表寫和壓縮I/O飽和了。

注: 
當使用LCS策略bootstrapping一個新節點到集羣中,Cassandra繞過了compaction操做。初始的數據被直接搬到正確的層級由於這兒沒有已有的數據,所以每一層沒有分片重複。獲取更多的信息,查看

優點: 磁盤空間的要求容易預測。讀操做的延遲更容易預測。過期的數據回收的更及時。

劣勢: 更高的I/O使用影響操做延遲。

TimeWindowCompactionStrategy(TWCS)

建議用在時間序列且設置了TTL的狀況。

TWCS有點相似於簡單設置的DTCS。TWCS經過使用一系列的時間窗口將SSTables進行分組。在compaction階段,TWCS在最新的時間窗口內使用STCS去壓縮SSTables。在一個時間窗口的結束,TWCS將掉落在這個時間窗口的全部的SSTables壓縮層一個單獨的SSTable,在SSTable maximum timestamp基礎上。一旦一個時間窗口的主要壓縮完成了,這部分數據就不會再有進一步的壓縮了。這個過程結束以後SSTable開始寫入下一個時間窗口。 

如上圖所示,從上午10點到上午11點,memtables flush到100MB的SSTables中。使用STCS策略將這些SSTables壓縮到一個更大的SSTables中。在上午11點的時候,這些SSTables被合併到一個單獨的SSTable,並且不會被TWCS再進行壓縮了。在中午12點,上午11點到中午12點建立的新的SSTables被STCS進行壓縮,在這個時間窗口結束的時候,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年紀(在一個SSTable中,每一列都標記着一個寫入的時間戳。)對於一個SSTable的年紀,DTCS使用SSTable中任意列中的oldest(最小的)時間戳。

配置DTCS時間戳

哪種壓縮策略最好

爲了實現最好的壓縮策略: 
1. Review 你應用的需求 
2. 配置表使用最合適的策略 
3. 測試壓縮策略

下面的問題基於有Cassandra 開發者和使用者的使用經驗以及上述描述的策略。

你的表處理的是時間序列的數據嗎

若是是的,你最好的選擇是TWCS 或者DTCS。想要看更多的細節,參考上面的描述。

若是你的表不是侷限於時間序列的數據,選擇就變得更加複雜了。下面的問題可能會給你其餘的考慮去作選擇。

你的表處理讀比寫多,或者寫多於讀嗎 
LCS 是一個好的選擇,若是表處理的讀是寫的兩倍或者更多——尤爲是隨機讀。若是讀的比重和寫的比重相似。LCS對性能的影響可能不值得獲取的好處。要意識到LCS可能會被一大批寫很快覆蓋掉。

表中的數據是否常常改變 
LCS的一個優點在於它將相關的數據都保持在小範圍的SSTables中,若是你的數據是不可更改的或者不是常常作upserts.STCS能夠實現相同類型的分組而不用付出LCS在性能上影響。

是否須要預測讀和寫等級 
LCS 保證SSTables在一個可預測的大小和數量中。例如,若是你的表讀/寫比例比較小,對於讀,指望得到一致的服務層面的一致性,或許值得付出寫性能的犧牲去確保讀速率和延遲在一個可預測的等級。並且能夠經過水平擴展(添加更多的節點)來克服掉寫入犧牲。

表會經過一個batch操做插入數據嗎 
batch 寫或batch讀,STCS表現的都比LCS好。batch過程形成不多或沒有碎片,所以LCS的好處實現不了,batch操做能夠經過LCS配置來覆蓋。

系統有受限的磁盤空間嗎 
LCS處理磁盤空間比STCS更高高效:除了數據自己佔用的空間,須要大約10%的預留空間。STCS和DTCS須要更多,在某些狀況下,差很少須要50%。

系統是否到達I/O限制 
LCS相比較DTCS 或者STCS,對I/O更加的敏感。換成LCS,可能須要引入更多的I/O來實現這種策略優點。

數據如何更新?

Cassandra將每一個新行都當作一個upsert:若是一個新行和一個已有的行有相同的primary key,Cassandra就會對這已有的行進行更新操做。

寫數據時,Cassandra將每一個新行都添加到數據庫中,而不去檢查是否有重複的記錄存在。這個方法將有可能致使相同行在數據庫中有多個版本存在。想要了解更多的信息,請查看數據如何寫入

間斷性的,存儲在內存中的行會被沖刷到磁盤中的叫作SSTables結構文件中。在一個肯定的間隔中,Cassandra將小的SSTables compacts成大的SSTables。若是在這個過程當中,Cassandra遇到2個或更多版本的同一行數據。Cassandra只會將最新版本的數據寫到新的SSTable。compaction結束後,Cassandra會刪除掉原來的SSTables,以及過期的行。

大部分的Cassandra環境會將每一行的副本存在兩個或多個節點上。每一個節點都獨立的執行compaction。這意味着即便一個過期版本的行數據在某個節點上被刪除了,可能仍然存在於其餘節點上。

這就是爲何Cassandra會在讀操做過程當中會執行另一輪比較。當一個客戶端根據一個特定的主鍵請求數據時,Cassandra會從一個或多個副本中產生多個版本的行數據。帶有最新的時間戳的數據是惟一會被返回到客戶端的數據(「最後寫贏策略」)。

注:數據庫操做可能只會更新一行數據的部分字段,所以有些版本的行只包括一些列,而不是所有。在寫操做和compaction階段,Cassandra從各個部分更新收集一個完整的行數據。每一列都使用最新的版本。

筆者注:

Cassandra更新數據不一樣於通常數據庫,不會更新原來的數據。只會追加新的數據。所以數據庫中可能會有多個版本的數據,會在compaction和repair階段去修復多個版本的行數據。以及在讀階段從多個版本的行數據中獲取最新的那行數據。 
另外cassandra每行每一個字段都有一個時間戳,因此行版本都是取每列的最新版本。

數據是如何刪除的

Cassandra刪除數據的過程是爲了提升性能,以及和Cassandra一些內置的屬性是實現數據的分佈,和故障容忍。

Cassandra將一個刪除視爲一個插入或者upsert。DELETE命令中添加的數據會被加上一個刪除標記,叫作墓碑。墓碑標記走的也是Cassandra寫過程,會被寫到一個或多個節點的SSTables。墓碑最主要的不一樣點在於:它有一個內置的過時日期/時間。在它過時的時候(更多細節在下面),墓碑會做爲Cassandra’compaction的一部分過程刪除掉。

在分佈式系統中作刪除操做

在一個多節點的集羣中,Cassandra能夠在2個或者更多的節點上存儲一份數據的多個副本。這樣能夠防止數據丟失,可是會使得刪除過程變得複雜。若是一個節點接收到刪除,在它存在本地,節點將這個特定記錄標記爲墓碑,而後嘗試將墓碑傳遞給其餘包含這個記錄的節點。可是若是某個存有該數據的節點在這個時間點沒有應答,不可以立刻收到墓碑,所以它仍會有這些記錄的刪除前的版本。若是在這個節點恢復過來以前,集羣中其餘被標記的墓碑數據都已經被刪除了,Cassandra會將恢復過來的這個節點上的這個記錄做爲新的數據,而且將它傳送到集羣的其餘節點。這種類型的刪除大可是仍存活下來的記錄叫作zombie

爲了阻止zombies從新出現,Cassandra給每一個墓碑一個grace時間段。grace時間段的目的就是給沒有應答的節點時間去回覆和正常處理墓碑。若是一個客戶端在grace period多墓碑數據寫入了一個新的更新。Cassandra會覆蓋掉墓碑。若是一個客戶端在grace時間段,讀墓碑記錄,Cassandra會無視墓碑,若是可能的話從其餘副本中讀取記錄。

當一個無應答的節點恢復過來,Cassandra使用hinted handoff來恢復節點down期間錯過的數據的更改。Cassandra不會去爲墓碑數據恢復更改在它grace period期間。可是若是在grace period結束後,節點尚未恢復,Cassandra會錯過刪除。

當墓碑的grace period結束後,Cassandra會在compaction階段刪除墓碑。

一個墓碑的grace period是經過設置gc_grace_seconds屬性來設置的。默認值是86400秒(10天)。每一個表這個屬性能夠單獨設置。

更多關於Cassandra刪除

細節:

  • 墓碑數據過時的日期/時間是它建立的日期/時間加上表屬性gc_grace_seconds值。

  • Cassandra也支持批量插入和更新。這個過程經過會帶來恢復一個記錄的插入的風險,當這條記錄已經被集羣的其餘節點移除掉了。Cassandra不會在grace period期間,爲一個墓碑數據恢復批量更改。

  • 在一個單節點的集羣中,你能夠設置gc_grace_seconds的值爲0

  • 爲了徹底阻止zombies記錄的再出現,在節點恢復過來後、以及每一個表的gc_grace_seconds,跑nodetool repair

  • 若是一個表的全部記錄在建立的時候設置了TTL,以及全部的都容許過時,且不能手動刪除,就沒有必要爲這張表按期跑nodetool repair

  • 若是使用了SizeTieredCompactionStrategy 或者 DateTieredCompactionStrateg,你能夠經過手動開啓compaction當即刪除掉墓碑。 
    當心: 
    若是你強制compaction,Cassandra可能從全部的數據中建立一個很是大的SSTable。Cassandra在很長的時間段中不會再觸發另一個compaction。在強制compaction期間建立的SSTable數據可能會變得很是過期在一個長的沒有compaction階段。

  • Cassandra 容許你爲整張表設置一個默認的_time_to_live屬性。列和行都被標記爲一個TTLs;可是若是一條記錄超過了表級別的TTL,Cassanda會當即將它刪除,而沒有標記墓碑或者compaction過程。

  • Cassandra支持經過DROP KEYSPACE 和 DROP TABLE當即執行刪除。

indexes是如何存儲和更新的

Secondary indexes是被用來過濾非primary key列的表查詢。例如,一個表存儲cyclist names 和ages。使用cyclist的last name做爲主鍵,可能會有一個age字段的secondary index,使得可以容許根據年齡來查詢。查詢匹配非主鍵的列是反範式的,由於這樣的查詢常常會致使表連續數據切片產生。

若是一個表根據last names時存儲數據,表將會分紅多個parittions存儲在不一樣的節點上。基於last names的某個特定範圍的查詢,好比全部的last name 爲Matthews名字的cyclists,會致使表的順序查詢,可是基於age的查詢,好比哪些cyclists 28歲,會致使全部節點都會去查一個值。不是primary keys在數據存儲時是亂序的。這種根據非主鍵的查詢會致使全partitions的掃描。掃描全部的partitions會致使很是高昂的讀延遲,是不被容許的。

Secondary indexes 能夠爲表的某一個列構建。這些indexes經過一個後臺進程都存儲在每一個節點的本地的一個隱藏表中。若是一個secondary index被用在一個查詢中並且沒有限制一個特定的partition key,這樣的query一樣會有高昂的查詢延遲,由於全部的節點都得查詢。帶這些參數的查詢只容許查詢選項爲 ALLOW FILTERING。這個選項不適用生產環境。若是一個查詢包括一個partiton key的條件和secondary index列條件,這樣的查詢纔會成功,由於會被轉換爲單個節點的分區。

然而這種技術並不能保證零麻煩的索引,所以須要知道何時用/不用index。像上面描述的例子,age列上的index可使用,可是更好的解決方案是建立一個物化視圖或者額外的一張根據age排序的表。

和關係型數據同樣,維護index須要處理時間和資源,所以沒必要要的indexes應該要避免。當一個列被更新的時候,它的index一樣須要更新。若是當一個老的列值還存在於memtable中,這個常常發生在重複的更新某些行,Cassandra會將對應的過期的index刪除;不然老的index entry仍然會被compaction清除掉。若是讀操做在compaction清理以前看到一個過期的index entry,reader線程會設置它無效。

注:

Casssandra Secondary Index介紹一文中有詳細介紹過Secondary Indx

數據是如何讀的

爲了知足讀,Cassandra必需要從存活的memtable和潛在的多個SSTables中聯合查詢結果。

Cassandra在讀的過程當中爲了找到數據存儲在何處,須要在好幾個階段處理數據。從memtables開始,到SSTables結束。

  • 檢查 memtable
  • 若是enabled了,檢查row cache
  • 檢查Bloom filter
  • 若是enable了,檢查partition key 緩存
  • 若是在partition key緩存中找到了partition key,直接去compression offset mao中,若是沒有,檢查 partition summary
  • 根據compression offset map找到數據位置
  • 從磁盤的SSTable中取出數據

讀請求流程圖 

行緩存和鍵緩存請求流程圖 

MemTable

若是memtable有目標分區數據,這個數據會被讀出來而且和從SSTables中讀出來的數據進行合併。SSTable的數據訪問以下面所示的步驟。

Row Cache

一般意義上,對於任何數據庫,當讀的大部分數據都在內存中讀取的時候是很是快的。操做系統的頁緩存是最有利提高性能的,通過行緩存對於讀佔比高的應用有必定性能提高,如讀操做佔95%。Row Cache對於寫佔比高的系統是禁用的。若是開啓了row cache.就會將一部分存儲在磁盤的SSTables數據存儲在了內存中。在Cassandra2.2+,它們被存儲在堆外內存,使用全新的實現避免形成垃圾回收對JVM形成壓力。存在在row cache的子集數據能夠在特定的一段時間內配置必定大小的內存。row cache使用LRU(least-recently-userd)進行回收在申請內存,當cache滿的時候。

row cache的大小是能夠配置的,值是能夠存多少行。配置緩存的行數是一個很是有用的功能,使得相似’最後的10條’查詢能夠很快。若是row cache 開啓了。目標的數據就會從row cache中讀取,潛在的節省了對磁盤數據的兩次檢索。存儲在row cache中的數據是SSTables中頻繁被訪問的數據。存儲到row cache中後,數據就能夠被後續的查詢訪問。row cache不是寫更新。若是寫某行了,這行的緩存就會失效,而且不會被繼續緩存,直到這行被讀到。相似的,若是一個partition更新了,整個partition的cache都會被移除,但目標的數據在row cache中找不到,就會去檢查Bloom filter。

Bloom Filter

首先,Cassandra檢查Bloom filter去發現哪一個SSTables中有可能有請求的分區數據。Bloom filter是存儲在堆外內存。每一個SSTable都有一個關聯的Bloom filter。一個Bloom filter能夠創建一個SSTable沒有包含的特定的分區數據。一樣也能夠找到分區數據存在SSTable中的可能性。它能夠加速查找partition key的查找過程。然而,由於Bloom filter是一個機率函數,因此可能會獲得錯誤的結果,並非全部的SSTables均可以被Bloom filter識別出是否有數據。若是Bloom filter不可以查找到SSTable,Cassandra會檢查partition key cache.

Bloom filter 大小增加很適宜,每10億數據1~2GB。在極端狀況下,能夠一個分區一行。均可以很輕鬆的將數十億的entries存儲在單個機器上。Bloom filter是能夠調節的,若是你願意用內存來換取性能。

Partition Key Cache

partition key 緩存若是開啓了,將partition index存儲在堆外內存。key cache使用一小塊可配置大小的內存。在讀的過程當中,每一個」hit」保存一個檢索。若是在key cache中找到了partition key。就直接到compression offset map中招對應的塊。partition key cache熱啓動後工做的更好,相比較冷啓動,有很大的性能提高。若是一個節點上的內存很是受限制,可能的話,須要限制保存在key cache中的partition key數目。若是一個在key cache中沒有找到partition key。就會去partition summary中去找。

partition key cache 大小是能夠配置的,意義就是存儲在key cache中的partition keys數目。

Partition Summary

partition summary 是存儲在堆外內存的結構,存儲一些partition index的樣本。若是一個partition index包含全部的partition keys。鑑於一個partition summary從每X個keys中取樣,而後將每X個key map到index 文件中。例如,若是一個partition summary設置了20keys進行取樣。它就會存儲SSTable file開始的一個key,20th 個key,以此類推。儘管並不知道partition key的具體位置,partition summary能夠縮短找到partition 數據位置。當找到了partition key值可能的範圍後,就會去找partition index。

經過配置取樣頻率,你能夠用內存來換取性能,當partition summary包含的數據越多,使用的內存越多。能夠經過表定義的index interval屬性來改變樣本頻率。固定大小的內存能夠經過index_summary_capacity_in_mb屬性來設置,默認是堆大小的5%。

Partition Index

partition index駐紮在磁盤中,索引全部partition keys和偏移量的映射。若是partition summary 已經查到partition keys的範圍,如今的檢索就是根據這個範圍值來檢索目標partition key。須要進行單次檢索和順序讀。根據找到的信息。而後去compression offset map中去找磁盤中有這個數據的塊。若是partition index必需要被檢索,則須要檢索兩次磁盤去找到目標數據。

Compression offset map

compression offset map存儲磁盤數據準確位置的指針。存儲在堆外內存,能夠被partition key cache或者partition index訪問。一旦compression offset map識別出來磁盤中的數據位置,就會從正確的SStable(s)中取出數據。查詢就會收到結果集。

注: 在一個分區裏,全部的行查詢代價並非一致的。在一個分區的開始(第一行,根據clustering key定義)想對來講代價更小,應爲沒有必要執行partition-level的index。

compression offset map 每TB增加量爲1~3GB。壓縮的數據越多,壓縮塊的數量越多,壓縮偏移表就會越大。Compression 默認是開啓的,即便壓縮過程當中會消耗CPU資源。開啓compression使得頁緩存更加的高效,一般來講是值得的。

注:

cassandra讀取的數據是memtable中的數據和SStables中數據的合併結果。讀取SSTables中的數據就是查找到具體的哪些的SSTables以及數據在這些SSTables中的偏移量(SSTables是按主鍵排序後的數據塊)。首先若是row cache enable了話,會檢測緩存。緩存命中直接返回數據。沒有查找Bloom filter,查找可能的SSTable。而後有一層Partition key cache,找partition key的位置。若是有根據找到的partition去壓縮偏移量映射表找具體的數據塊。若是緩存沒有,則要通過Partition summary,Partition index去找partition key。而後通過壓縮偏移量映射表找具體的數據塊。

讀是如何影響寫的

思考集羣中寫操做會對讀操做有什麼影響是很是重要的。compaction 策略的類型使得數據的處理是可配置的,同時會影響讀的性能。使用SizeTieredCompactionStrategy或者DateTieredCompactionStrategy可能會在行被頻繁更新的時候形成數據碎片化。LeveledCompactionStrategy(LCS)在這種狀況下是被設計用來阻止數據碎片化的。

相關文章
相關標籤/搜索