軟件測試數據庫中NoSQL漫談
NoSQL,意即反SQL運動(dòng),是一項全新的數據庫革命性運動(dòng),早期就有人提出,發(fā)展至2009年趨勢越發(fā)高漲。NoSQL的擁護者們提倡運用非關(guān)系型的數據存儲,相對于目前鋪天蓋地的關(guān)系型數據庫運用,這一概念無(wú)疑是一種全新的思維的注入。
什么是NoSQL?wiki上的定義是“NoSQL is a movement promoting a loosely defined class of non-relational data stores that break with a long history of relational databases”。其實(shí)并不存在一個(gè)叫NoSQL的產(chǎn)品,它是一類(lèi)non-relational data stores的集合。NoSQL的重點(diǎn)是non-relational,而傳統的數據庫是relational。
我們都知道,傳統關(guān)系型數據庫的最大缺陷是擴展性,雖然各個(gè)數據庫廠(chǎng)家都有cluster的解決方案,但是不管是share storage還是share nothing的解決方案,擴展性都十分有限。目前解決數據庫擴展性的思路主要有兩個(gè):第一是數據分片(sharding)或者功能分區,雖然說(shuō)可以很好的解決數據庫擴展性的問(wèn)題,但是在實(shí)際使用過(guò)程中,一旦采用數據分片或者功能分區,必然會(huì )導致?tīng)奚瓣P(guān)系型”數據庫的最大優(yōu)勢-join,對業(yè)務(wù)局限性非常大,而數據庫也退化成為一個(gè)簡(jiǎn)單的存儲系統。另外一個(gè)思路是通過(guò)maser-slave復制的方式,通過(guò)讀寫(xiě)分離技術(shù)在某種程度上解決擴展性的問(wèn)題,但這種方案中,由于每個(gè)數據庫節點(diǎn)必須保存所有的數據,這樣每個(gè)存儲的IO subsystem必然成為擴展的瓶頸,而且masert節點(diǎn)也是一個(gè)瓶頸?偟膩(lái)說(shuō),傳統關(guān)系型數據庫的擴展能力十分有限。
在說(shuō)NoSQL之前,首先得說(shuō)兩個(gè)重要的概念,一個(gè)是CAP理論,另一個(gè)是BASE模型。
CAP
Consistency(一致性),數據一致更新,所有數據變動(dòng)都是同步的
Availability(可用性),好的響應性能
Partition tolerance(分區容錯性) 可靠性
CAP原理告訴我們,這三個(gè)因素最多只能滿(mǎn)足兩個(gè),不可能三者兼顧。對于分布式系統來(lái)說(shuō),分區容錯是基本要求,所以必然要放棄一致性。對于大型網(wǎng)站來(lái)說(shuō),分區容錯和可用性的要求更高,所以一般都會(huì )選擇適當放棄一致性。對應CAP理論,NoSQL追求的是AP,而傳統數據庫追求的是CA,這也可以解釋為什么傳統數據庫的擴展能力有限的原因。
BASE
Basically Availble:基本可用
Soft-state: 軟狀態(tài)/柔性事務(wù)
Eventual Consistency:最終一致性
BASE模型是傳統ACID模型的反面,不同與ACID,BASE強調犧牲高一致性,從而獲得可用性;究捎檬侵竿ㄟ^(guò)sharding,允許部分分區失敗。軟狀態(tài)是指異步,允許數據在一段時(shí)間內的不一致,只要保證最終一致就可以了。最終一致性是整個(gè)NoSQL中的一個(gè)核心理念,很多NoSQL產(chǎn)品就是基于最終一致性而設計的,包括Amazon的Dynamo.
NoSQL產(chǎn)品簡(jiǎn)介
NoSQL是很多non-relational data stores的集合,總體來(lái)說(shuō),他們基本都是基于Key-value形式的一種分布式存儲,但是每一種NoSQL產(chǎn)品都面向一個(gè)特定的應用場(chǎng)景,根據這些應用場(chǎng)景,我們可以把NoSQL分為以下類(lèi)型(參考了wiki上的定義,只列舉了我們比較熟悉的產(chǎn)品):
KV cache:Memcached
KV store:Tokyo Tyrand/Cab.net,Memcachedb,Berkley DB
Eventually consistent KV store:dynamo,voldemort,Cassandra
Wide columnar store:BigTable,Cassandra,Hbase
document store:MongoDB
KV Cache類(lèi)型不具有持久化存儲的功能,其中的memcached被我們廣泛使用,用來(lái)緩解數據庫的壓力,至于數據持久化存儲的功能則由數據庫來(lái)替代了。
KV store具備了持久化存儲的功能,其中的memcachedb是新浪在memcached的基礎上,采用Berkley DB作為存儲層開(kāi)發(fā)的分布式KV store。Tokyo Tyrand/Cabinet是日本最大的SNS社交網(wǎng)站mixi.jp開(kāi)發(fā)的KV store,其中TC是一個(gè)NoSQL的數據庫,用來(lái)做持久化數據存儲,TT則是TC的網(wǎng)絡(luò )接口(兼容memcached協(xié)議)。至于Berkley DB則是一個(gè)嵌入式數據庫,現在掌握在Oracle手中。
Eventually consistent KV store是以最終一致性原理設計的一類(lèi)KV store,包括Amazon的Dynamo,Lindedin的voldemort以及Facebook的Cassandra,Dynamo的主要特點(diǎn)是:分布式(去中心化),高可用,可擴展,永遠可寫(xiě)等等。Dynamo的設計思想是分布式系統中最重要的理論之一,另外一個(gè)是Bigtable。
Wide columnar store包括Bigtable,Cassandra和Hbase,這種類(lèi)型是用來(lái)處理結構化數據的,它有幾個(gè)特點(diǎn):具備大規模擴展能力,有類(lèi)似數據庫中column的概念,非常靈活的schema,采用memtable/sstable的存儲機制,并基于列存儲。Cassandra采用了Dynamo最終一致性的理念,并借鑒了Bigtable的數據模型和實(shí)現方式,所以很多人把他看作是開(kāi)源版本的Bigtable+Dynamo,這種類(lèi)型的KV store是我們關(guān)注的重點(diǎn)。
document store是基于文檔的KV store,這種類(lèi)型主要面向海量數據處理,其中MongoDB的特點(diǎn)是支持非常復雜的數據類(lèi)型,而且查詢(xún)語(yǔ)言非常強大,有些類(lèi)似于關(guān)系型數據庫。但它并不適合大規模并發(fā)讀寫(xiě)的應用。
下面介紹幾個(gè)分布式系統的概念:consistent hashing,virtual node,quorum,vector clock:
consistent hashing
我們通常使用的hash算法是hash() mod n,但是如果發(fā)生某個(gè)節點(diǎn)失效時(shí),無(wú)法快速切換到其他節點(diǎn)。為了解決單點(diǎn)故障的問(wèn)題,我們?yōu)槊總(gè)節點(diǎn)都增加一個(gè)備用節點(diǎn),當某個(gè)節點(diǎn)失效時(shí),就自動(dòng)切換到備用節點(diǎn)上,類(lèi)似于數據庫的master和slave。但是依然無(wú)法解決增加或刪除節點(diǎn)后,需要做hash重分布的問(wèn)題,也就是無(wú)法動(dòng)態(tài)增刪節點(diǎn)。這時(shí)就引入了一致性hash的概念 ,將所有的節點(diǎn)分布到一個(gè)hash環(huán)上,每個(gè)請求都落在這個(gè)hash環(huán)上的某個(gè)位置,只需要按照順時(shí)針?lè )较蛘业降牡谝粋(gè)節點(diǎn),就是自己需要的服務(wù)節點(diǎn)。當某個(gè)節點(diǎn)發(fā)生故障時(shí),只需要在環(huán)上找到下一個(gè)可用節點(diǎn)即可。一致性hash解決了增刪節點(diǎn)后需要hash重分布的問(wèn)題,是分布式系統的基礎。
virtual node
虛擬節點(diǎn)是在一致性hash的基礎上,把一臺物理節點(diǎn)虛擬成多個(gè)虛擬節點(diǎn),并映射到hash環(huán)的不同位置上。這樣的好處是可以根據機器硬件的性能,靈活的定義虛擬節點(diǎn)的個(gè)數。這里所說(shuō)的虛擬節點(diǎn)不是用虛擬機技術(shù)實(shí)現的,而是把一個(gè)物理節點(diǎn)映射為多個(gè)虛擬節點(diǎn)。
quorum NRW
N: 復制的節點(diǎn)數,即一份數據被保存的份數。
R: 成功讀操作的最小節點(diǎn)數,即每次讀取成功需要的份數。
W: 成功寫(xiě)操作的最小節點(diǎn)數 ,即每次寫(xiě)成功需要的份數。
這三個(gè)因素決定了可用性,一致性和分區容錯性。對于一個(gè)分布式系統來(lái)說(shuō),N通常都大于3,也就說(shuō)同一份數據需要保存在三個(gè)以上不同的節點(diǎn)上,以防止單點(diǎn)故障。W是成功寫(xiě)操作的最小節點(diǎn)數,這里的寫(xiě)成功可以理解為“同步”寫(xiě),比如N=3,W=1,那么只要寫(xiě)成功一個(gè)節點(diǎn)就可以了,另外的兩份數據是通過(guò)異步的方式復制的。R是成功讀操作的最小節點(diǎn)數,讀操作為什么要讀多份數據呢?在分布式系統中,數據在不同的節點(diǎn)上可能存在著(zhù)不一致的情況,我們可以選擇讀取多個(gè)節點(diǎn)上的不同版本,來(lái)達到增強一致性的目的。下面我們分析幾個(gè)典型的場(chǎng)景:
N=W,R=1,這種情況是最強一致性的,每個(gè)節點(diǎn)都被同步寫(xiě)入,讀取任意節點(diǎn)即可,所以讀取的性能最高,但是可用性是最差的,因為必須保證每個(gè)節點(diǎn)都必須成功寫(xiě)人。
R+W>N,這種情況也是可以保證一致性的,因為讀取數據的節點(diǎn)和同步寫(xiě)入的節點(diǎn)至少有一個(gè)重疊,比如N=3,W=2,R=2,每份數據有三個(gè)復本,每次同步寫(xiě)成功兩份數據,每次讀取至少兩份數據,則說(shuō)明讀取的數據至少有一份是同步寫(xiě)人的最新數據,所以一致性可以得到保證,N=3,W=2,R=2是可用性和性能的一個(gè)平衡。
N=R,W=1,這種情況最大程度保證了寫(xiě)的性能,數據只寫(xiě)一份即成功,而讀取時(shí)則需要所有的數據復本,以此來(lái)達到保證一致性的目的,但是同樣犧牲了可用性。
W+R<=N,這種情況是不保證一致性的,因為讀取和寫(xiě)入的節點(diǎn)可能存在不重疊的情況,在數據同步到其他節點(diǎn)的這段時(shí)間窗口內,可能會(huì )出現數據不一致的情況。
文章來(lái)源于領(lǐng)測軟件測試網(wǎng) http://kjueaiud.com/