您好,登錄后才能下訂單哦!
這篇文章給大家介紹如何了解Cassandra數(shù)據(jù)庫(kù),內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。
Cassandra數(shù)據(jù)庫(kù),值得介紹的技術(shù)細(xì)節(jié)其實(shí)挺多的。因?yàn)樗芏鄬?shí)現(xiàn)思路和關(guān)系型數(shù)據(jù)庫(kù)或者其他的NoSQL數(shù)據(jù)庫(kù),是有一些不同的。這種不同是在數(shù)據(jù)庫(kù)設(shè)計(jì)實(shí)現(xiàn)思路上也是根源上的。所以衍生開來的諸多特點(diǎn),在介紹起來就不太容易和其他數(shù)據(jù)庫(kù)去類比。
我把這幾大特性分為四類:
第一類開源,這個(gè)不需要討論。其余的三類7個(gè)特性,就是選講的核心提綱。
第二類是高可用、容錯(cuò)性、可配置的一致性,這是圍繞著多節(jié)點(diǎn)冗余數(shù)據(jù)的特性,換句話說,如果Cassandra的數(shù)據(jù),每一行數(shù)據(jù)只有一份而沒有副本,那么第二類特點(diǎn)就是不存在的。
第三類是分布式、去中心化、可擴(kuò)展性,這三個(gè)特點(diǎn)圍繞的是數(shù)據(jù)庫(kù)的可拆分性,且各節(jié)點(diǎn)可以獨(dú)立運(yùn)行的能力。若只裝一個(gè)單機(jī)的Cassandra,那這一類特點(diǎn)就不存在。
第四類是行存儲(chǔ),是描述數(shù)據(jù)庫(kù)底層存放數(shù)據(jù)的最基本的存儲(chǔ)結(jié)構(gòu)特征,也是我切入的第一個(gè)特征。
行存儲(chǔ)結(jié)構(gòu)
任何數(shù)據(jù)庫(kù)設(shè)計(jì)和優(yōu)化始終圍繞一個(gè)核心事情——查詢優(yōu)化。查詢永遠(yuǎn)是使用數(shù)據(jù)的核心需求。為什么要INSERT?為了以后這個(gè)數(shù)據(jù)要查詢。為什么要DELETE?因?yàn)椴辉俨樵?,并且讓其他的?shù)據(jù)更快的查詢。為什么要UPDATE,因?yàn)橐獙?shí)時(shí)的查詢使用。無論是數(shù)據(jù)庫(kù)的存儲(chǔ)結(jié)構(gòu),像ORACLE的段、區(qū)、塊的設(shè)計(jì),還是輔助的存儲(chǔ)結(jié)構(gòu),像索引這種,歸根結(jié)底,為了更快速的查詢出需要數(shù)據(jù)。Cassandra也不例外,了解它的存儲(chǔ)結(jié)構(gòu),就更加能夠理解它是如何在這個(gè)存儲(chǔ)體系下提高查詢性能的,即便它是一個(gè)號(hào)稱更擅長(zhǎng)于INSERT的數(shù)據(jù)庫(kù)。
在早期的Cassandra中,數(shù)據(jù)庫(kù)表一直被稱之為ColumnFamily(列族),我也有很長(zhǎng)的時(shí)間將其理解為列的集合的意思。所以,我有一段時(shí)間認(rèn)為Cassandra是一個(gè)列存儲(chǔ)的數(shù)據(jù)庫(kù)。那為什么Cassandra的數(shù)據(jù)模型,可以認(rèn)為是行存儲(chǔ)(ROW-ORIENTED)的,但又會(huì)在早期表被稱之ColumnFamily呢?因?yàn)閺母旧蟻碇v,Cassandra不能算一個(gè)嚴(yán)格的行存儲(chǔ),當(dāng)然它更不是列存儲(chǔ),它的數(shù)據(jù)是存儲(chǔ)在一個(gè)稀疏矩陣中的??赡苓@個(gè)解釋略微抽象。那么我先來說下它為什么不是行存儲(chǔ)。
任何傳統(tǒng)的行存儲(chǔ)數(shù)據(jù)庫(kù),一旦DDL定義了數(shù)據(jù)表有多少個(gè)列。那么這一行數(shù)據(jù)一定存儲(chǔ)了所有的列值。即使出現(xiàn)了這一列沒有值的情況,那么也一定存儲(chǔ)了一個(gè)NULL值,或者是由應(yīng)用程序存儲(chǔ)一個(gè)空格或0來表示沒有值。這一列對(duì)應(yīng)的存儲(chǔ)空間一定是存在的,當(dāng)然數(shù)據(jù)庫(kù)中的varchar或者壓縮算法會(huì)使得這個(gè)存儲(chǔ)空間盡可能小。
但是,Cassandra允許對(duì)于任何給定的行,你可以只包含其中幾列,而并非一行數(shù)據(jù)要有所有的列,當(dāng)然KEY列是要有的。這種在列值存儲(chǔ)上的動(dòng)態(tài)性,是傳統(tǒng)的行存儲(chǔ)數(shù)據(jù)庫(kù)根本不具備的。我猜這也可能早期為何有ColumnFamily概念的根源。
前文提到了,我有一段時(shí)間認(rèn)為Cassandra是一個(gè)列存儲(chǔ)的數(shù)據(jù)庫(kù)。但是,我從來都認(rèn)為它是一個(gè)不徹底的列存儲(chǔ)數(shù)據(jù)庫(kù),而是一個(gè)受限的列存儲(chǔ)數(shù)據(jù)庫(kù)。不徹底在哪里?大部分的列存儲(chǔ)數(shù)據(jù)庫(kù),都是為了OLAP而生的,它的優(yōu)勢(shì)在于,在某一列上做聚合的性能無語倫比。
比如我一個(gè)表有100列,我要對(duì)某一列求個(gè)SUM。列存儲(chǔ)數(shù)據(jù)庫(kù)可以完美繞過多余的99列,只把需要的這一列一個(gè)不差的拿出來做SUM。但是,用過Cassandra數(shù)據(jù)庫(kù)的人都知道,在任何一列上做全列級(jí)的聚合,那簡(jiǎn)直是災(zāi)難性的。就憑Cassandra會(huì)將不同的KEY部署在不同的數(shù)據(jù)庫(kù)節(jié)點(diǎn)/分區(qū)PARTITION(注意這里和傳統(tǒng)數(shù)據(jù)庫(kù)分區(qū)不同),任何列級(jí)的操作,都會(huì)需要在多個(gè)數(shù)據(jù)庫(kù)上打轉(zhuǎn)。更何況,CQL語句到來的時(shí)候,還要搞清楚,這個(gè)聚合列在這行數(shù)據(jù)上有沒有。所以,Cassandra是不具備列存儲(chǔ)數(shù)據(jù)庫(kù)的特質(zhì)的。
為什么,最后Cassandra還是被描述為是一個(gè)ROW-ORIENTED呢?
首先,它的存儲(chǔ)是緊緊圍繞著Key的。Key,它是一行數(shù)據(jù)的唯一標(biāo)識(shí)符號(hào)。一行數(shù)據(jù)圍繞著Partition Key存在一起,并且圍繞著Clusterting Key局部有序??梢娝黂OW-ORIENTED的特點(diǎn)還是很鮮明的。什么樣的存儲(chǔ)結(jié)構(gòu),就決定一個(gè)數(shù)據(jù)庫(kù)擅長(zhǎng)做什么。按主鍵排序的行存儲(chǔ)DB2數(shù)據(jù)庫(kù)最擅長(zhǎng)的是什么?是在OLTP系統(tǒng)里,通過主鍵做單條記錄的快速查詢(Select by Key),這也正是Cassandra最為常見的CQL形態(tài)。什么樣的存儲(chǔ)結(jié)構(gòu),也決定了什么樣的操作會(huì)有限制。
在理解了Cassandra數(shù)據(jù)庫(kù)的ROW-ORIENTED的稀疏矩陣存儲(chǔ)之后,再來看看CQL語句的語法限制,那么這些限制就很容易理解。例如:Select 語句,Where條件里,一定要送Partition Key(沒有次索引的情況)。如果不送,則語法上必須要添加ALLOW FILTERING。
為什么是這樣,剛才提到了,Partition Key決定了數(shù)據(jù)存在哪里,它像是一個(gè)指針,直接指向了這一行數(shù)據(jù)的物理位置。ALLOW FILTERING表示什么,表示的是Cassandra數(shù)據(jù)庫(kù)獲得這條記錄是通過篩選得來的,而不是通過直接定位得來的。
類比一下傳統(tǒng)數(shù)據(jù)庫(kù),Where 條件送Partition Key就好比通過HASH索引定位記錄,ALLOW FILTERING就如同先做一次TABLE SCAN,讀出大量記錄再?gòu)挠涗浝镞^濾出符合WHERE條件的。再看看關(guān)于Clusterting Key的,CQL語法要求,范圍查找、Order by一類的語法都需要使用Clusterting Key,這就十分好理解。在定位的Partition Key確定了位置之后,同一Partition Key的數(shù)據(jù),都是Clusterting Key有序存放的,那么通過在這個(gè)有序的Key列上,無論范圍也好、排序也好,都不會(huì)需要數(shù)據(jù)庫(kù)引擎真正去排序,這就好像在傳統(tǒng)數(shù)據(jù)庫(kù)里,ORDER BY的列,和某一個(gè)索引一致的情況下,執(zhí)行計(jì)劃里不會(huì)真的排序是一個(gè)道理。
搞清楚了Cassandra的存儲(chǔ)結(jié)構(gòu)之后,我們來看Cassandra在某一個(gè)節(jié)點(diǎn)上怎么做增刪改查。無論Cassandra的多節(jié)點(diǎn)特點(diǎn)多么鮮明,在單一節(jié)點(diǎn)上面,數(shù)據(jù)的讀寫,永遠(yuǎn)才是數(shù)據(jù)庫(kù)性能的根基。節(jié)點(diǎn)再多,如果單節(jié)點(diǎn)上讀寫性能不行,那數(shù)據(jù)庫(kù)終究是快不起來的。所以這里我們來看一下,Cassandra是怎么樣讀寫數(shù)據(jù)的。
先翻譯《Cassandra The Definitive Guide》一段話?!霸贑assandra中,寫入數(shù)據(jù)非??欤?yàn)樗膍emtables和SSTables設(shè)計(jì),使它插入時(shí),不需要執(zhí)行磁盤讀取或搜索,這些減慢數(shù)據(jù)庫(kù)速度的操作。Cassandra中的所有寫入都是追加形態(tài)的?!?/p>
我們看一下Cassandra的寫入步驟,來解讀它的寫入優(yōu)勢(shì)。
第一步,寫Commit Logs。這個(gè)步驟完全不是什么新發(fā)明。我覺得它和傳統(tǒng)數(shù)據(jù)庫(kù)的REDO Log幾乎是一樣的。無論是什么數(shù)據(jù)庫(kù),這個(gè)Log的寫入,都是追加形態(tài)的。但是,注意看這個(gè)圖,Commit Logs直接寫在硬盤上,我認(rèn)為這個(gè)描述并不準(zhǔn)確。無論時(shí)傳統(tǒng)數(shù)據(jù)庫(kù)的REDO LOG還是Cassandra 的Commit Logs,它都是先到內(nèi)存,再FLUSH到磁盤上的。而FLUSH的策略是由一些參數(shù)決定的,比如commitlog_sync。這和傳統(tǒng)數(shù)據(jù)庫(kù)非常相似,這里不展開來討論,只需要認(rèn)識(shí)到一點(diǎn),F(xiàn)LUSH的動(dòng)作頻率越高,系統(tǒng)奔潰時(shí)丟失的數(shù)據(jù)越少,同時(shí)損失部分?jǐn)?shù)據(jù)插入性能。就像Mysql數(shù)據(jù)庫(kù)的參數(shù)Innodb_flush_log_at_trx_commit=1時(shí),Mysql是最安全,但是也是最慢的。
第二步,Add to memtable,這是關(guān)鍵的一步,Cassandra的這一步是完完全全的內(nèi)存動(dòng)作。而若是傳統(tǒng)的數(shù)據(jù)庫(kù),則大約需要做這么幾個(gè)動(dòng)作:
逐層搜索索引,若這個(gè)索引塊不在DATA BUFFER里,觸發(fā)磁盤IO。
通過索引定位數(shù)據(jù)塊,若數(shù)據(jù)塊不在DATA BUFFER里,觸發(fā)磁盤IO。
修改索引塊,修改數(shù)據(jù)塊,如果修改并發(fā)量大時(shí),可能產(chǎn)生鎖等。
當(dāng)然,若是像Oracle數(shù)據(jù)庫(kù)那樣的堆表設(shè)計(jì),純粹的INSERT動(dòng)作在b的IO觸發(fā)可能性要少一點(diǎn),但是在UPDATE(Cassandra中也是Insert)場(chǎng)景下,這些開銷都是不可少的。Cassandra為什么可以在Memtable上純粹的做追加寫入,這個(gè)Cassandra記錄的Timestamp概念是分不開的,即無論你寫入多少次,數(shù)據(jù)庫(kù)只會(huì)以最新Timestamp的記錄為準(zhǔn)。這樣就不需要去對(duì)記錄資源上鎖。這樣的設(shè)計(jì),不要說沒有鎖沖突了,就連去把需要上鎖的記錄找出來的開銷都省了,快就快在這個(gè)地方。
但是,這個(gè)快是有代價(jià)的,那就是數(shù)據(jù)的一致性。比如一個(gè)簡(jiǎn)單的需求,在數(shù)據(jù)寫入之前,需要看看這條數(shù)據(jù)是不是存在,如果存在了就不能插入(CQL的IF NOT EXIST語法),或者UPDATE需要看數(shù)據(jù)條件(WHERE IF Column = ‘*’) 。一旦這種帶條件CQL使用,那可以推斷,上面的這些優(yōu)勢(shì),也就不存在了。
看第三步,如果這行數(shù)據(jù)在Row Caches里,使它失效。注意這個(gè)地方,Row Caches里的記錄是不改的。那么Row Caches的使用場(chǎng)景,只有特別熱點(diǎn)的數(shù)據(jù)讀取的時(shí)候使用,它并不適合高并發(fā)熱點(diǎn)數(shù)據(jù)修改的場(chǎng)景。
常規(guī)交易,做完這三步就返回成功了,不需要等待Memtable的內(nèi)容落盤。換句話說,直接影響交易性能的步驟,結(jié)束了。這和傳統(tǒng)數(shù)據(jù)庫(kù)也沒有太大的差別。那么接下來的步驟,就不直接影響數(shù)據(jù)庫(kù)的寫入能力。
第四步,數(shù)據(jù)的落盤,這個(gè)動(dòng)作通常是異步的,在后面會(huì)詳細(xì)展開將SSTable的存儲(chǔ)。第五步,這個(gè)就是多節(jié)點(diǎn)特性了,是一個(gè)節(jié)點(diǎn)異常的處理過程。
總結(jié)一下,傳統(tǒng)的數(shù)據(jù)庫(kù)的寫入(包括INSERT、UPDATE、Delete),通常是一個(gè)讀后寫的過程。而Cassandra的寫入,是沒有先讀這個(gè)動(dòng)作的,這也是它快的根本原因。一旦使用了IF NOT EXIST之類的語法,那么它的寫入性能也就會(huì)要受損。
接下來看一下Cassandra的讀取,它的讀取是多節(jié)點(diǎn)、多副本的讀取。此處,我們先關(guān)注一個(gè)節(jié)點(diǎn)上的情況。
第一步,如果這一行數(shù)據(jù)在Row Caches中,直接返回?cái)?shù)據(jù),這個(gè)好理解。
第二步,檢查檢查KeyCaches里的索引,這里可以理解為,這是一個(gè)主鍵索引,它存儲(chǔ)的是未來在Memtables或者SSTables用來定位的信息(書上原文是offset location)。需要注意的是,這里面的值,在第三步、和第四步的時(shí)候,都可能用得上,而不是僅僅用于第三步??吹竭@個(gè)地方,可以發(fā)現(xiàn),其實(shí)這個(gè)圖有個(gè)問題,就是沒有指出KeyCaches的維護(hù)。Cache是可以在建表時(shí)配置的一個(gè)參數(shù)。可以推測(cè),假如我們建表的時(shí)候,keys的Cache采用了ALL的設(shè)置,那么應(yīng)該是在有新的KEY值寫入Memtables時(shí),維護(hù)到了Key Caches中。
第三步,這一步需要關(guān)注是,對(duì)于一個(gè)指定的表(或列族),是只會(huì)使用唯一的一個(gè)Memtable 的,那么這個(gè)搜索就是線性的。Memtable中的內(nèi)容,是還沒有FLUSH到SSTables里的數(shù)據(jù),在查詢是,它里面的內(nèi)容和SSTables中的內(nèi)容,都是要同步讀取的,但對(duì)單節(jié)點(diǎn)而言,它的內(nèi)容通常更新。
與寫入場(chǎng)景大有不同的地方是,讀數(shù)據(jù)的關(guān)鍵步驟,是第4步,讀SSTables。這里在后面的內(nèi)容展開,看一下第五步,如果Row Caches還可用,把這條記錄加入的Row Caches。Row Caches放的是一整行的數(shù)據(jù),如前面提到了,適合于存放熱點(diǎn)讀取的數(shù)據(jù)。
所有的數(shù)據(jù)庫(kù),通常都是有四大常規(guī)操作,謂之“增刪改查”。介紹了寫入、查詢之后,這里簡(jiǎn)單的介紹一下Cassandra的刪和改。一句話簡(jiǎn)述之,Cassandra的刪除都是修改,Cassandra的修改都是寫入,所以Cassandra只有寫入和查詢。Cassandra一直寫入數(shù)據(jù),豈不是會(huì)存儲(chǔ)爆炸不成。在這里,我們介紹三個(gè)新概念(相對(duì)傳統(tǒng)數(shù)據(jù)庫(kù))-Tombstones,Timestamps,Compaction。
Cassandra的刪除都是修改,這個(gè)好理解,在很多業(yè)務(wù)數(shù)據(jù)庫(kù)表里面,經(jīng)常會(huì)為了保留痕跡,而做一個(gè)邏輯刪除動(dòng)作。也就是修改某個(gè)標(biāo)識(shí),表示這條記錄以及刪除或作廢,而并沒有在數(shù)據(jù)庫(kù)里真正的刪除。Cassandra在收到Delete命令時(shí),并不會(huì)立刻去刪除這行記錄。而是會(huì)給這行記錄一個(gè)Tombstones,表示它被刪除了。
Cassandra的修改都是寫入。前面提到Cassandra速度快,快在不需要定位數(shù)據(jù)。任何Update命令,在傳統(tǒng)數(shù)據(jù)庫(kù)上,都需要把這條記錄讀到內(nèi)存里,并上鎖。而在Cassandra上,Update命令會(huì)變成一條INSERT語句,那豈不是在系統(tǒng)里重KEY了嗎?這里便要依靠記錄上的Timestamps。
Cassandra的每次查詢,都會(huì)把所有重的KEY讀出來,但是永遠(yuǎn)會(huì)以最新的Timestamps為準(zhǔn)。這就解決了把所有的修改,都變成寫入的問題。但是,這么干有兩大顯而易見問題。第一,數(shù)據(jù)會(huì)無限的膨脹,吃掉磁盤。第二,數(shù)據(jù)膨脹會(huì)帶來查詢需要讀出的重復(fù)數(shù)據(jù)增加,無限的膨脹則會(huì)無限的增加,讀取性能就會(huì)受損。
所以這里,就要介紹壓縮(Compaction)的概念。這里要特別的注意,這不是我們通常說的數(shù)據(jù)庫(kù)壓縮技術(shù),那個(gè)通常用的Compress。只是由于多個(gè)官方文檔都把Compaction翻譯成了壓縮,我個(gè)人覺得它更應(yīng)該翻譯成數(shù)據(jù)的整理。Compaction是在數(shù)據(jù)庫(kù)后臺(tái)異步做的,接著前面的內(nèi)容,它的內(nèi)容至少有比如把墓碑?dāng)?shù)據(jù)真實(shí)移除,把時(shí)間戳比較老的數(shù)據(jù)移除,重新整理SSTable的存儲(chǔ)文件等。這樣來解決前面那兩個(gè)問題。這個(gè)動(dòng)作在某種意義上來講甚至有一點(diǎn)像DB2數(shù)據(jù)庫(kù)的REORG動(dòng)作。不同的數(shù)據(jù)庫(kù)表,可以在Keyspace級(jí)別選擇不一樣的CompactionStrategy。它常翻譯為壓縮算法,我覺得翻譯成整理策略更加合適。我覺壓縮算法,應(yīng)該和Compress的那個(gè)概念一致。畢竟,這個(gè)Compaction沒有給數(shù)據(jù)文件里連續(xù)的值,用個(gè)RLE算法,或者建個(gè)字典什么的對(duì)吧。介紹完了這些之后,讓我們來直面數(shù)據(jù)庫(kù)最大的瓶頸。
只要一個(gè)數(shù)據(jù)庫(kù)不是內(nèi)存數(shù)據(jù)庫(kù),那它永遠(yuǎn)都要面對(duì)它最大的性能瓶頸,磁盤IO。我們前面提到的諸多概念,比如Cache、列存儲(chǔ)、索引等等,他們優(yōu)化性能的本質(zhì)都指向一處,減少磁盤IO。前面講讀寫部分時(shí),都跳過了第4步。而對(duì)于SSTable的讀取,其實(shí)才是影響性能的關(guān)鍵步驟。
我們來看一下,SSTable到底是什么,它的讀取是什么樣子的。我們根據(jù)SSTable的訪問順序來看,在3.0版本中,SSTable包含以下這么幾個(gè)文件:
Filter.db這是SSTable的Bloom過濾器,簡(jiǎn)單的講,它告訴你,你要的Key,在我這里有沒有。Bloom過濾器的工作方式是將數(shù)據(jù)集中的值映射到位數(shù)組,并使用散列函數(shù)將較大的數(shù)據(jù)集壓縮為摘要字符串。根據(jù)定義,摘要使用的內(nèi)存量比原始數(shù)據(jù)少得多。它速度快,可能誤報(bào),但不會(huì)漏。簡(jiǎn)言之,有可能告訴你有,但是沒有。但絕不會(huì)告訴沒有,卻有。注意!這里劃一個(gè)重點(diǎn),Cassandra會(huì)維護(hù)一個(gè)Bloom filter的副本在內(nèi)存里面。所以,這一步不一定會(huì)有實(shí)際IO。在書上也提到,如果加大內(nèi)存,是可以減少Bloom過濾器誤報(bào)的情況。
Summary.db,這里是索引的抽樣,用來加速讀取的。
Index.db,提供Data.db里的行列偏移量。
CompressionInfo.db提供有關(guān)Data.db文件壓縮的元數(shù)據(jù)。這里值得關(guān)注的是,它用了Compression這個(gè)詞,我猜測(cè),如果Data.db里面采用了壓縮算法,比如說字典壓縮之類的,那么這個(gè)文件里面應(yīng)該就會(huì)存儲(chǔ)字典數(shù)據(jù),或者類似的Compress相關(guān)的元素?fù)?jù)。這也就是為什么這個(gè)文件,在訪問流程中是不可繞過的。因?yàn)橐坏〥ata.db的數(shù)據(jù)進(jìn)行了壓縮,那就必須依靠相關(guān)的元數(shù)據(jù)來解壓縮數(shù)據(jù)。從圖上可以看出,這個(gè)元數(shù)據(jù)在內(nèi)存中,相對(duì)性能會(huì)比較快。
Data.db是存儲(chǔ)實(shí)際數(shù)據(jù)的文件,是Cassandra備份機(jī)制保留的唯一文件。它是唯一的真實(shí)數(shù)據(jù),其他的都是輔助數(shù)據(jù)。比如索引可以重建,字典可以重建等等。
Digest.adler32是Data.db校驗(yàn)用的。
Statistics.db存儲(chǔ)nodetool tablehistograms命令使用的有關(guān)SSTable的統(tǒng)計(jì)信息。
TOC.txt列出此SSTable的文件組件。
其中1-5是跟SSTable訪問數(shù)據(jù)性能相關(guān)的文件。如果Cache是ALL的情況下,Cassandra在通常都可以在內(nèi)存訪問之后,直接定位到SSTable的具體文件和數(shù)據(jù)所在偏移量中去。相對(duì)于傳統(tǒng)數(shù)據(jù)庫(kù),B樹索引層層向下,遇到?jīng)]有的索引塊就要IO。這個(gè)性能應(yīng)該還是非常可觀的。
講到這里,不知道你有沒有感受到,Cassandra的一個(gè)重要精華所在,那就是沒有鎖,或者叫沒有資源上的沖突和爭(zhēng)搶。通過Timestamps概念,解決數(shù)據(jù)可相同Key數(shù)據(jù)不要上鎖的問題。盡管我們前面的內(nèi)容,全部都還只是在圍繞單節(jié)點(diǎn)數(shù)據(jù)庫(kù)介紹。但是Timestamps的使用,是為Cassandra分布式、去中心、可擴(kuò)展、高可用、容錯(cuò)性、可配置一致性提供了更多靈活方便的地方。
分布式、去中心、可擴(kuò)展性
前面我們把這六條分成了兩類,分布式、去中心、可擴(kuò)展,這三個(gè)圍繞的是KEY的獨(dú)立性。尤其是Partition Key,它是具有極強(qiáng)的獨(dú)立性的。由于它的極度獨(dú)立,理論上任何不同Partition Key的數(shù)據(jù),就都可以放在不同機(jī)器上,去獨(dú)立的提供服務(wù),也就成就它的分布式、去中心和可擴(kuò)展。對(duì)照這幾條特性看一下。
分布式,百度詞條上解釋為,建立在網(wǎng)絡(luò)上的軟件系統(tǒng)。有四大特性:
分布性。分布式系統(tǒng)由多臺(tái)計(jì)算機(jī)組成,它們?cè)诘赜蛏鲜欠稚⒌?,可以散布在一個(gè)單位、一個(gè)城市、一個(gè)國(guó)家,甚至全球范圍內(nèi)。整個(gè)系統(tǒng)的功能是分散在各個(gè)節(jié)點(diǎn)上實(shí)現(xiàn)的,因而分布式系統(tǒng)具有數(shù)據(jù)處理的分布性。一個(gè)邏輯上的數(shù)據(jù)庫(kù)表,他是分散存儲(chǔ)來多個(gè)Node中的。不同的Key值的記錄會(huì)由Cassandra的不能節(jié)點(diǎn)提供分散的的服務(wù)。
自治性。分布式系統(tǒng)中的各個(gè)節(jié)點(diǎn)都包含自己的處理機(jī)和內(nèi)存,各自具有獨(dú)立的處理數(shù)據(jù)的功能。通常,彼此在地位上是平等的,無主次之分,既能自治地進(jìn)行工作,又能利用共享的通信線路來傳送信息,協(xié)調(diào)任務(wù)處理。Cassandra只有在Partition Key劃分?jǐn)?shù)據(jù)所屬Node的存儲(chǔ)位置時(shí),有主次副本之分。比如說,我的Node1要存放的Key值是多少到多少,其他的勉強(qiáng)稱之為副本。其實(shí)Cassandra存的是多個(gè)地位平等主本,且都具備獨(dú)立處理數(shù)據(jù)等能力,它們協(xié)同處理任務(wù),并非傳統(tǒng)意義上的主備數(shù)據(jù)概念。
并行性。一個(gè)大的任務(wù)可以劃分為若干個(gè)子任務(wù),分別在不同的主機(jī)上執(zhí)行。每個(gè)Node自然是自己提供涉及的Key的服務(wù),相互之間獨(dú)立、并行。對(duì)于不同的CQL而言,可能會(huì)由不同Node來完成查詢。也可以是一個(gè)CQL里面涉及的多個(gè)Node,它們也基本上是并行來完成這個(gè)CQL的。
全局性。分布式系統(tǒng)中必須存在一個(gè)單一的、全局的進(jìn)程通信機(jī)制,使得任何一個(gè)進(jìn)程都能與其他進(jìn)程通信,并且不區(qū)分本地通信與遠(yuǎn)程通信。同時(shí),還應(yīng)當(dāng)有全局的保護(hù)機(jī)制。系統(tǒng)中所有機(jī)器上有統(tǒng)一的系統(tǒng)調(diào)用集合,它們必須適應(yīng)分布式的環(huán)境。在所有CPU上運(yùn)行同樣的內(nèi)核,使協(xié)調(diào)工作更加容易。Cassandra是完全符合這個(gè)定義的,Coordinator節(jié)點(diǎn)并不是固定的。每個(gè)節(jié)點(diǎn)都可以接受任何的CQL,并且來充當(dāng)協(xié)調(diào)者的角色。重要的是,對(duì)于一個(gè)應(yīng)用程序或者客戶端而且,可以不關(guān)心Cassandra后來是怎么樣存儲(chǔ)和查詢數(shù)據(jù)的。它從外面看到的,始終只有一張完整的邏輯數(shù)據(jù)表。
有了分布式的基礎(chǔ),Cassandra可以運(yùn)行在多個(gè)Node下,并且多個(gè)Node可以部署在真實(shí)的不同的數(shù)據(jù)中心機(jī)房里,不同機(jī)架上,也就能做到去中心Decentralized。有了這個(gè)基礎(chǔ),就可以配合Cassandra的多中心的復(fù)制策略NetworkTopologyStrategy,在每一個(gè)數(shù)據(jù)中心定義數(shù)據(jù)復(fù)制了。
可擴(kuò)展這個(gè)詞其實(shí),并不是特別準(zhǔn)確,它的重點(diǎn)其實(shí)是可水平擴(kuò)展。簡(jiǎn)而言之,就是在圖中環(huán)上加Node,就可以提高Cassandra的處理能力。這其實(shí)和它的分布式特點(diǎn)是密不可分的。Cassandra的拆分粒度最細(xì),理論上幾乎可以到一個(gè)Partition KEY。或者說,每一個(gè)Partition KEY,都可以被看作可以拆分的,獨(dú)立處理的最小的單位。增加數(shù)據(jù)的同時(shí)只要增加Node就可以了,這就使得它的水平擴(kuò)展性是很好的。
做一個(gè)偏激的假設(shè),如果Cassandra只有一份數(shù)據(jù)存儲(chǔ),就憑Key獨(dú)立的特點(diǎn),把不同的Key分到不同的機(jī)器上提供服務(wù),也可以算得上是分布式、去中心和可擴(kuò)展的。但是它這個(gè)特點(diǎn)是不完美,不徹底的。因?yàn)闄C(jī)器分得越多,任何一臺(tái)機(jī)器故障,它提供的服務(wù)就是不完整的。
高可用、容錯(cuò)性、可配置一致性
接下來,我們繼續(xù)看另外三個(gè)特點(diǎn),高可用、容錯(cuò)性、可配置的一致性,這些特點(diǎn)圍繞的核心就數(shù)據(jù)冗余。
任何的高可用背后,一定是有數(shù)據(jù)冗余的。傳統(tǒng)數(shù)據(jù)庫(kù)通常偏愛的是主備模式,就是當(dāng)提供服務(wù)的數(shù)據(jù)庫(kù)節(jié)點(diǎn)DOWN掉之后,備節(jié)點(diǎn)開始提供服務(wù)。這時(shí)候往往故障檢測(cè)、主備切換,應(yīng)用切換的時(shí)間就會(huì)成為關(guān)注的焦點(diǎn),做得好一點(diǎn)的數(shù)據(jù)庫(kù)可以在1分鐘或者幾十秒內(nèi)完成切換。不過在如今7*24*365的環(huán)境下,1分鐘的故障恢復(fù)時(shí)間通常并不能讓用戶十分滿意,當(dāng)切換時(shí)間壓縮到一定程度,還會(huì)出現(xiàn)一個(gè)矛盾點(diǎn),就是數(shù)據(jù)庫(kù)異常時(shí)間監(jiān)測(cè)閾值。如果設(shè)得太長(zhǎng),主備切換就慢,設(shè)太短了,一個(gè)網(wǎng)絡(luò)抖動(dòng),就可能觸發(fā)不必要的主備切換誤判。
Cassandra的數(shù)據(jù)復(fù)制(replicas)并不像傳統(tǒng)的備份數(shù)據(jù),它更像是多份主數(shù)據(jù),這些數(shù)據(jù)都是時(shí)時(shí)刻刻對(duì)外提供服務(wù)的,換句話說,有一個(gè)數(shù)據(jù)庫(kù)節(jié)點(diǎn)DOWN掉,完全不需要主備切換時(shí)間。在資源充足的情況下,甚至是幾乎無感的(比如7個(gè)replicas壞了1個(gè))。
在Cassandra里面,數(shù)據(jù)復(fù)制(replicas)多少份,怎么存儲(chǔ),這個(gè)策略是可以根據(jù)不同的Keyspace來設(shè)置的,相當(dāng)于提供一個(gè)靈活的選擇,可以根據(jù)數(shù)據(jù)庫(kù)表的實(shí)際使用場(chǎng)景和形態(tài),來決定數(shù)據(jù)復(fù)制的策略。
數(shù)據(jù)冗余可以說是分布式系統(tǒng)中的常規(guī)操作,像參數(shù)數(shù)據(jù)之類的,經(jīng)常會(huì)采用數(shù)據(jù)冗余的方法來處理。然而,有冗余的地方就有同步。數(shù)據(jù)一致性問題,永遠(yuǎn)和數(shù)據(jù)冗余相伴而生。好在Cassandra有Timestamps來解決一致性問題,容錯(cuò)性只是一致性的一個(gè)衍生產(chǎn)品,簡(jiǎn)單的說,只是Cassandra發(fā)現(xiàn)了一個(gè)老Timestamps的錯(cuò)誤數(shù)據(jù),后臺(tái)修復(fù)一下而已。
而可配置一致性,就是Cassandra的一個(gè)特別重要的特性了。因?yàn)樗挠绊懙粌H僅是對(duì)于高可用,它還直接影響數(shù)據(jù)庫(kù)性能。就傳統(tǒng)數(shù)據(jù)庫(kù)而言,開不開備庫(kù),對(duì)OLTP交易性能也是有直接影響的(包括Redis也是)。從理論上來說,Cassandra要等更多的Node寫入數(shù)據(jù),那響應(yīng)時(shí)間就會(huì)越慢。這個(gè)響應(yīng)時(shí)間取決與最慢的那個(gè)Node。若要交易響應(yīng)更快,就需要通過異步的方式。所以Cassandra通常都不會(huì)等所有的Node都響應(yīng),等多少Node,等哪些Node,就是可配置一致性。
在數(shù)據(jù)寫入讀取方面Cassandra的一直性級(jí)別有:
ANY(僅寫入),ONE,TWO,THREE ,QUORUM,ALL
LOCAL_ONE, LOCAL_QUORUM,EACH_QUORUM
以上這些級(jí)別很好理解,不需要逐個(gè)解釋。關(guān)于高可用和強(qiáng)一致性,永遠(yuǎn)都是魚和熊掌。假如我們的系統(tǒng)使用了最快的方式寫入,比如寫ANY,讀ONE。那么讀到的數(shù)據(jù)并不是最實(shí)時(shí)的準(zhǔn)確數(shù)據(jù)的可能性就會(huì)大幅增加。如上面的圖,有6個(gè)節(jié)點(diǎn)在寫入數(shù)據(jù),任意一個(gè)寫成功,程序就成功返回。那么假定其余5個(gè)節(jié)點(diǎn)還沒有完成寫入。那這時(shí)候,有一個(gè)讀ONE的程序,恰好讀到了這5節(jié)點(diǎn)中的一個(gè),并成功返回,這就產(chǎn)生了數(shù)據(jù)的不一致。要做到數(shù)據(jù)的強(qiáng)一致,讀寫策略就必須配合設(shè)置,滿足這樣的條件。
W+R>RF W—寫一致性級(jí)別 R—讀一致性級(jí)別 RF—副本數(shù)
Cassandra的這個(gè)設(shè)計(jì)非常的巧妙,它提供極好的調(diào)優(yōu)靈活性。數(shù)據(jù)庫(kù)調(diào)優(yōu)的本質(zhì)無非是個(gè)損有余而補(bǔ)不足的過程,這個(gè)有余并非指損性能好的地方去補(bǔ)性能不好的地方。
數(shù)據(jù)庫(kù)或數(shù)據(jù),有些地方有些功能,我們不用或者少用,性能不需要那么好,稱之為有余;有些地方有些功能我們常用,主要用,性能要越快越好,我們稱之為不足。比如很多系統(tǒng)的某個(gè)數(shù)據(jù)庫(kù)表,它的訪問形態(tài)是有局限性的。有可能一張表,100次插入,只有1次讀取,像流水?dāng)?shù)據(jù)。有可能一張表,1次插入,100次讀取,像參數(shù)數(shù)據(jù)。這里面就有了極大的靈活性,我們可以損失冷門操作的性能,來保障我們的主要操作。例如,以讀取為主的表,我們可以設(shè)置寫入的一致性為ALL ,讀取的一致性為ONE。從而獲得一個(gè)非常高效的系統(tǒng)性能。
需要注意的是,數(shù)據(jù)的復(fù)制因子,是定義在Keyspace,也就是在存儲(chǔ)方面決定。而讀取的一致性,是由客戶端決定的。同樣的數(shù)據(jù),也可以根據(jù)不同使用場(chǎng)景來使用不同的一致性級(jí)別。比如說,對(duì)數(shù)據(jù)實(shí)時(shí)性要求高時(shí),可以設(shè)置成讀QUORUM或者ALL,實(shí)時(shí)性要求低時(shí),選擇讀ONE。
總結(jié)
至此,我已經(jīng)完整的講解了Cassandra的分布式、去中心化、可擴(kuò)展性、高可用、容錯(cuò)性、可配置的一致性、行存儲(chǔ)的特性。
回顧一下,我們先講了Cassandra單節(jié)點(diǎn)上的行存儲(chǔ)結(jié)構(gòu),然后圍繞Cassandra數(shù)據(jù)Key的獨(dú)立性介紹了分布式、去中心化、可擴(kuò)展性。繼而討論了關(guān)于Cassandra多副本數(shù)據(jù)帶來的高可用、容錯(cuò)性、和可配置一致性。
當(dāng)然Cassandra數(shù)據(jù)庫(kù)還有很多值得探討和介紹的內(nèi)容和概念,如Secondary Index、Tokens、Hinted等等。此外在Cassandra數(shù)據(jù)庫(kù)的使用過程中,也還有監(jiān)控、備份恢復(fù)、性能調(diào)優(yōu)、安全等等內(nèi)容值得關(guān)注學(xué)習(xí),這里就不一一介紹了,未來有機(jī)會(huì),再做續(xù)集吧。
關(guān)于如何了解Cassandra數(shù)據(jù)庫(kù)就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。