Apache Cassandra 4.0新特性介紹

DataStax發表於2020-08-21

引言

大家好,我是蔡一凡,是Cassandra的貢獻者之一。(雖然我不便透露我的公司名稱),但目前我們公司Cassandra的部署是全世界最大的之一,Cassandra在我們公司也有很多的應用。


Cassandra是一個擁有high-scalability(高伸縮性)、high-availability(高可用性)的資料庫。接下來,我們來看一下Cassandra 4.0將會為我們帶來什麼新的令人激動的特性。


首先,不久之前,Cassandra 4.0-beta1已經發布了,在釋出這個版本之前,總共有超過三年多的開發、修復、測試時間。在這一版本中,多了很多好用的功能,也修復了大量的bugs,並且新增了多個測試工具。這些測試工具會帶來更多型別的測試用例,從而提高測試的覆蓋譜。在Cassandra 4.0中,測試是一個重中之重。因為社群的共識是,Cassandra 4.0會被作為史上最穩定版本來推出。

 

截止4.0-beta1這個版本,我們共有571項程式碼變更, 這個可以在Cassandra Repository裡面看到。這些變更主要包括新功能和bugs的修復,但是大量對於不穩定測試的修復是不包括在內的,所以如果從commits的數量來說其實變化的地方還要多很多。

 


 

 

新功能介紹

今天我主要帶來的是Cassandra 4.0版本中作為亮點的新功能,包括了稽核日誌、零拷貝串流、Netty節點間通訊、虛擬表、增量式修復、臨時副本。


稽核日誌

稽核日誌的功能是將資料庫所有活動記錄到一個本地檔案,這些活動包括authentication,還有所有的CQL請求,不論成功與否都會被記錄下來。


稽核日誌的效能是很高的,因為它預設的格式是二進位制,所以它有很快的寫入效能。而且由於並非向Cassandra資料庫中寫入,所以執行稽核日誌對其它資料庫操作的影響是比較小的,不太會影響資料庫的效能。


稽核日誌這個功能有很多的用途,譬如利用記錄來debug線上碰到的問題,也可以幫助做測試。比如在4.0中同步推出的full query logger就是用稽核日誌來實現的,這些由full query logger生成的記錄可以在之後用來做回放測試。另外,稽核日誌也可以幫助企業做合規管理,因為所有的活動都可以被記錄到檔案,企業的稽核也可以有所依據。


零拷貝串流

在介紹零拷貝串流之前,我想先介紹一下資料串流的場景。


用過Cassandra的同學應該都知道,在node(節點)啟動(bootstrap)時,它會從副本節點將資料串流過來,資料修復時也會有資料串流的現象。另外,執行nodetool rebuild時節點也會跟其副本節點進行串流。除此之外,在現有叢集中增加、替換、移除節點時,節點都會從別的副本節點或向別的副本節點串流資料。最後一個場景就是節點的token被修改時,不屬於某個節點的token範圍的資料,就會被串流到新的負責該資料的token的其它節點。總而言之,在Cassandra中,串流會被應用於很多場景。基本所有資料在叢集中被複制時都會發生這個現象。


回過頭看,零拷貝串流的“零拷貝”是指在串流時無需將資料讀到記憶體後再寫入到網路。零拷貝串流只需要傳送方和接收方可以直接通過網路傳送和接收資料。當然,這個功能其實是依賴於作業系統的。如果執行Cassandra的系統支援這個功能,那麼可以大大提升傳輸速度。因為零拷貝串流不需要把資料讀到記憶體中,所以也避免建立相關的物件,繼而減少了對於GC的壓力。


接下來,我們看一下Netflix做的一個測試。首先我先簡單介紹他們的測試是怎麼做的。Netflix在相同的硬體條件下,進行了多次的A/B測試,並得到一個結果的分佈。A/B測試中主要是對比3.0版本和4.0版本串流所用的時間。其中,3.0版本使用的是普通串流,而4.0版本使用的是零拷貝串流。串流的時間是怎麼獲得的呢?在一個叢集,測試人員將其中的一個節點替換掉,並統計新節點串流所用的時間。在四種不同的硬體條件下分別進行了同樣的實驗,以便於比較。


PPT中可以看到有四個箱型圖,每個箱型圖最上面的線是多次測試中的最長時間,最下面的線是多次測試中的最短時間。箱型圖中間還有一條線,這是多次測試結果的中位數。箱子的上沿是多次測試結果中的75百分位;箱子的下沿則是多次測試結果中的25百分位。而圖中洋紅色的箱子則是普通串流得到的資料,而灰藍色則是零拷貝串流得到的資料。


在圖中,我們可以一目瞭然地看到,在不同的硬體條件下,零拷貝串流所需的時間都是遠遠小於普通串流所需的時間的。另外,零拷貝串流的箱子也會比較短一些,這表示在多次測試的基礎上,可以發現其效能的穩定性是很高的。零拷貝串流在不同的硬體條件下執行,所需時間都比較相近。因為對於零拷貝串流來說,資料不需要被載入到記憶體中,CPU也不需要浪費時間去處理這些資料,所以零拷貝串流所需要的時間主要是與硬碟和網路卡的速度有關,反而與CPU的關係不大。反觀普通串流,我們可以看到在不同硬體下,它所需要的時間的分佈是有很大波動的。相比之下,零拷貝串流比普通串流提高了3-5倍的速度。


前面說到,零拷貝串流是直接把資料通過網路埠傳送出去,所以與CPU bound相對,零拷貝串流是一個I/O bound的功能。另外,由於零拷貝串流大大提升了串流速度,所以它幫助縮短了每一個節點的平均恢復時間。恢復時間是指,如果有一個節點出現故障了,在改節點被修復之後需要從別的副本節點中傳輸相應的資料。當資料修復傳輸的速度更快,節點所需的平均恢復時間就被縮短了,也就是說,節點處於“不可用(unavailable)”狀態的時間會被縮短。這樣也會相應減少多個節點可能同時處於不可用狀態的概率。除此之外,零拷貝串流可以幫助降低運維成本。舉例來說,當我們要把一個節點的資料遷移到一個新的節點,如果資料傳輸的過程可以更快完成,原來的節點就可以更早地被關閉,這樣可以幫助減少一部分的開銷。


Netty節點間通訊

如果有讀過Cassandra原始碼的同學可能會知道,Cassandra在3.0、2.1、2.0這些版本是根據叢集中的節點來分配執行緒的。一般來說,每個節點會被分配三個執行緒用來通訊,這三個執行緒分別負責體積較小的資訊、體積較大的資訊以及較為緊急的資訊。


在4.0版本中,我們把這個架構改成了Netty。I/O是非阻塞的,不再按節點分配執行緒。


接下來的這幾個資料同樣是來自Netflix,是通過在一個192個節點的Cassandra叢集中進行測試得到的。在測試中,我們比較了4.0版本和3.0版本。我們發現4.0版本的延遲會更低(平均值減少40%,99分位的延遲減少了60%),且吞吐量更高(大約2倍的提升)。

 

另外,4.0版本的記憶體佔用更少,原因是4.0版本中對inbound和outbound連線的實現進行了改進。對於outbound,Cassandra有自己的Frame Encoder。它不同於Netty的Frame Encoder的一點是它避免了多次的記憶體拷貝,也就是說,它在使用handler時不會先寫入很多記憶體,只有Frame有的時候它才會寫入。對於inbound,Cassandra也有自己的Frame Decoder的實現。當接收到足夠多的資料之後,Cassandra的Frame Decoder才會做解壓縮的處理,並且對於未處理訊息的個數也做了限制。如果inbound的訊息太多,就會被block,相當於對別的節點實現了back pressure的功能。


最後一點是節點間加密通訊擴充套件性更高,主要是得益於Netty的tcnative。它跟JDK自帶的的加密效能相比,大概提升了有4倍。


總而言之,通過改進到使用Netty節點間通訊,Cassandra叢集中各個節點間的通訊變得更有效率。


虛擬表

虛擬表之所以被叫做虛擬表,是因為並沒有硬碟上的資料與之對應。虛擬表是虛擬的,它其實是基於Cassandra內部的一些API實現的,所以我們可以把虛擬表當作Cassandra的一個介面。


目前來說,虛擬表是隻讀性質的。也就是說,我們只可以對Cassandra的一些狀態進行查詢,但是並不能通過虛擬表對系統狀態和配置做出改變。每一個虛擬表都是每個節點所特有的,也就是說虛擬表是local的。


怎麼操作虛擬表呢?我們可以通過CQL來進行查詢,從而獲取Cassandra的系統狀態和當前配置。另外,因為有了虛擬表,我們可以不用JMX,CQL Clients也可以通過CQL介面方便地進行查詢。


接下來我們來看一下虛擬表大概的樣子。


所有的虛擬表都是位於system_views這個keyspace下面,PPT中加粗的部分就是目前有的虛擬表。比如其中有一個是settings,這個表中列出了當前Cassandra的配置。


歡迎大家下載Cassandra 4.0 Docker image來體驗更多其它的虛擬表,這裡就不一一展示了。


增量式修復

首先,增量式修復並不是4.0中的新功能,在Cassandra 2.1中這個功能就已經被推出了。但是在當時的版本中,這個功能存在一些問題,所以並不適用於在生產環境中使用。Cassandra 4.0所做的主要工作就是把之前的很多問題修復了。


在我們更多地介紹增量式修復之前,我們先簡單介紹一下什麼是“修復”。在Cassandra執行時,節點間資料隨著時間的推移會出現不一致的情況。“修復”功能就是用來解決節點間資料不一致的問題。粗略地說,每個節點都會比較本地和副本節點的資料,如果發現資料有差別,“修復”功能就會幫助同步這些節點的資料,從而達到整個叢集中資料一致的效果。但是普通的修復有一個問題,就是這個操作是比較昂貴的——執行時間較長,且執行期間會增加query的延遲。


在此基礎上,增量式修復的意思就是不再修復已經修復過的資料。它的實現大概是將資料分為“已修復”和“未修復”兩個部分,每次修復時只修復“未修復”的部分。這樣,每次修復的時間就會減少。因此,我們可以更頻繁地使用增量式修復,而每次修復只需要幾分鐘時間即可完成。


在4.0之前,增量式修復的問題到底是什麼呢?其實主要是overstreaming(過度傳輸)的問題。過度傳輸的意思是,某一份資料因為之前的修復在某一節點已經存在,但是增量式修復出於某些原因無法識別該資料已經在節點被修復,所以這份資料又被重新串流到別的節點。比如說現在正在修復一個SSTable,這時有一個後臺例行的Compaction task(壓縮任務)把這個SSTable壓縮之後又產生一個新的SSTable。這個時候,這個新產生的SSTable不會被標記成已修復,在下一次增量修復時,這個新的SSTable會被認為資料和別的節點不一致,所以資料又會被重新傳送一次。這也就導致了overstreaming的問題。


新的增量式修復把這個過程做成了一個可以被回撤的transaction。也就是說如果發生了前面說的問題,所有當前repair的sessions都會被標記為失敗,相關的SSTable也會回滾到“未被修復的SSTable”的池裡面。


臨時副本

臨時副本是4.0版本的試驗性功能,還有很多的限制,所以並不推薦用在生產環境中,但是有興趣的同學可以先提前嚐鮮。


在臨時副本之前,我先介紹一下什麼是完全副本。在4.0之前的replica就是完全副本,因為4.0多了臨時副本,所以講以前的replica起了個新的名字以區別兩種副本。


在PPT的圖中有一個由三個節點組成的叢集,這三個節點都是完全副本。當replication factor等於3時,每個節點負責的資料都會有三個備份。也就是說,假設一個叢集共有3TB的資料,刨去副本之後其實只有1TB資料,即三分之二的儲存空間是被浪費掉的。


臨時副本主要就是用來解決這個問題的。臨時副本節點只儲存沒有修復的資料,在修復之後,這些資料就會被臨時副本節點刪除。也就是說這些資料是臨時的,這也是為什麼我們管它叫“臨時副本”。


這個功能最好是和增量式修復一起使用,因為這樣我們可以很快地從臨時副本節點中將未修復的資料修復,之後再刪除掉。這樣一來,我們可以認為臨時節點並不佔用儲存空間。依舊使用前面的例子:當replication factor為3,其中一個節點作為臨時節點。這樣一來,我們減少使用了三分之一的儲存空間。在大規模叢集中,如果可以減少三分之一的儲存空間,這將會是一大進步。

臨時節點是這樣工作的:當有寫入操作時,寫操作會優先考慮完全副本;當完全副本出現故障或下線時,寫操作才會寫到臨時副本節點。關於讀操作,我們只要保證當前副本集裡面有一個完全副本就可以,因為只要增量式修復一直在執行,完全副本就肯定會被修復。拿PPT中的圖舉例,如果節點1變成不可用狀態,只有節點2和3也還是可以保證讀操作能滿足Quorum的read query。當然,如果讀操作要求consistency level = ALL的話,這種情況就不能滿足要求了,原來也是不行的。


另外,臨時節點的增加依然可以保證原有的可用性的承諾,相同consistency level的query在有臨時副本節點的叢集中與只有完全副本節點的叢集是可以等效的。當一個有臨時副本節點的Cassandra叢集變成不可用的狀態時,它所失去的節點數目和只有完全副本節點的叢集也是一致的。所以從這一點來說,加入臨時副本節點對於使用Cassandra的應用來說是完全透明的,也就是說應用是完全不會察覺到臨時副本節點的使用的。


臨時副本節點帶來的好處包括上面提到的,當RF = 3時,使用一個臨時節點可以減少33%的儲存。另外,因為臨時節點只保留臨時資料,資料量比較小,修復完就刪除,所以這個節點會使用更少的CPU和I/O。除此之外,臨時副本還保留了永續性的保證。也就是說,在只有完全副本節點時能滿足什麼consistency level的query,使用了臨時副本節點之後還是有這樣的保證。

 


 

結束語

以上就是Cassandra 4.0中比較重要的新功能。


最後總結一下,Cassandra 4.0增加了多項新功能,帶來了增強的效能、更快的串流速度以及更高的可靠性。整個社群也花費了最長的時間來測試Cassandra 4.0,以確保Cassandra 4.0是Cassandra史上最穩定的版本。


歡迎大家有時間時體驗一下Cassandra 4.0。 

相關文章