引子
VoltDB是一個(gè)宣稱性能超過Mysql 100倍的新型數(shù)據(jù)庫(kù)。它源自Micheal Stonebraker一篇論文H-Store。在這篇論文發(fā)表后,Stonebraker成立了VoltDB公司帶著他的一些學(xué)生開始在OLTP數(shù)據(jù)庫(kù)領(lǐng)域打拼。Stonebraker從上世紀(jì)70年代——數(shù)據(jù)庫(kù)剛開始發(fā)展的時(shí)間——就開始在數(shù)據(jù)庫(kù)領(lǐng)域活躍,這樣的老古董提出的數(shù)據(jù)庫(kù)的新想法,給了整個(gè)存儲(chǔ)領(lǐng)域很大的想象空間。
VoltDB源起于應(yīng)用領(lǐng)域與硬件發(fā)展翻天覆地的變化。用戶的使用方法發(fā)生了變化,在數(shù)據(jù)庫(kù)開始發(fā)展的階段,事務(wù)是一個(gè)較長(zhǎng)的過程,用戶或者管理員可以在”BEGIN TRANSACTION”和”END TRANSACTION”之間慢慢地人工執(zhí)行整個(gè)事務(wù)的步驟。但是現(xiàn)在,大部分操作是由Web服務(wù)端發(fā)起的書寫良好的事務(wù),用戶訪問的是Web服務(wù)器,在Web服務(wù)器的執(zhí)行邏輯里再訪問數(shù)據(jù)庫(kù),所以即使是很復(fù)雜的事務(wù)也可以很快執(zhí)行完。計(jì)算機(jī)硬件的發(fā)展更是一日千里。幾十GB的內(nèi)存服務(wù)器已經(jīng)很常見。以太網(wǎng)絡(luò)也已經(jīng)步入Gbps時(shí)代,而且正在朝向10Gbps方向邁進(jìn)。基于以太網(wǎng)的集群的機(jī)器價(jià)格也降低到比PC機(jī)貴不了太多。VoltDB的設(shè)計(jì)充分利用了這些特點(diǎn),數(shù)據(jù)主要存儲(chǔ)在內(nèi)存中,Shared Nothing的集群結(jié)構(gòu),單機(jī)是單線程處理事務(wù),不是用鎖而是基于Optimistic的方法處理事務(wù)并發(fā),所有的事務(wù)必須以存儲(chǔ)過程形式先提交到VoltDB系統(tǒng)。下面分開來說。
事務(wù)提交
既需要支持復(fù)雜的事務(wù)操作,又需要快速的執(zhí)行過程,VoltDB采取了一個(gè)比較極端的事務(wù)提交方式。雖然VoltDB支持部分SQL語(yǔ)句接口,但是不允許用戶使用傳統(tǒng)的”BEGIN TRANSACTION”和”END TRANSACTION”的語(yǔ)法模式,而是完全基于存儲(chǔ)過程。用戶通過寫存儲(chǔ)過程完成應(yīng)用程序的邏輯,作為一個(gè)先置條件將存儲(chǔ)過程提交到VoltDB。運(yùn)行時(shí),用戶程序調(diào)用存儲(chǔ)過程完成事務(wù)操作,所有事務(wù)的運(yùn)行邏輯是由VoltDB在服務(wù)器進(jìn)程中完成的。這種方式保證了事務(wù)不會(huì)被人為打斷,并且服務(wù)器可以預(yù)先判斷各個(gè)事務(wù)的邏輯,也為事務(wù)并發(fā)處理挖掘信息。
數(shù)據(jù)分布
VoltDB使用Shared Nothing結(jié)構(gòu),整個(gè)數(shù)據(jù)庫(kù)的數(shù)據(jù)分散到集群的多臺(tái)機(jī)器上。VoltDB的數(shù)據(jù)分布策略是基于哈希的,存儲(chǔ)在VoltDB中的每一張表,對(duì)數(shù)據(jù)的主鍵哈希取模后的結(jié)果對(duì)應(yīng)于數(shù)據(jù)存儲(chǔ)的節(jié)點(diǎn)。相比較于BigTable基于主鍵的連續(xù)范圍分段的方法,哈希方法的好處是數(shù)據(jù)分散的均勻,沒有動(dòng)態(tài)數(shù)據(jù)調(diào)整的煩惱。但也有很多缺點(diǎn),采用這種方法后,集群的規(guī)模是事先確定好的,新增機(jī)器需要停止服務(wù)后重新分布數(shù)據(jù)。另外,數(shù)據(jù)哈希被分散后,數(shù)據(jù)的連續(xù)性被打亂了,在這個(gè)數(shù)據(jù)結(jié)構(gòu)上做范圍查詢需要?jiǎng)佑梅?wù)這張表的所有機(jī)器,這個(gè)后面會(huì)祥說。
上面這張圖描述了數(shù)據(jù)的分布方式,VoltDB集群的每臺(tái)機(jī)器都會(huì)服務(wù)多張表。從圖里還能看到VoltDB的數(shù)據(jù)復(fù)制是基于機(jī)器單位的,藍(lán)色框圈住的兩臺(tái)機(jī)器內(nèi)的數(shù)據(jù)是完全同構(gòu)的。
VoltDB的哈希分布數(shù)據(jù)的方法是系統(tǒng)設(shè)計(jì)的簡(jiǎn)化,這種簡(jiǎn)化讓VoltDB工程實(shí)現(xiàn)難度降低,可以快速的商用。天下沒有免費(fèi)的午餐,這個(gè)設(shè)計(jì)也是VoltDB功能缺陷,導(dǎo)致VoltDB無法動(dòng)態(tài)擴(kuò)容以及其他一些問題。
數(shù)據(jù)一致性
同一份數(shù)據(jù)的多個(gè)副本之間需要保證數(shù)據(jù)一致性,VoltDB采用所有修改操作在每一個(gè)副本上單獨(dú)更新的方式。如何保證更新操作在所有副本上以相同的順序更改而不至于產(chǎn)生不一致,這就要提到VoltDB的并發(fā)控制方式。
VoltDB的事務(wù)并發(fā)控制需要依賴于集群內(nèi)所有機(jī)器的時(shí)間是一致的,這個(gè)可以使用NTP之類的時(shí)間同步協(xié)議,保證機(jī)器之間的時(shí)間差異遠(yuǎn)遠(yuǎn)小于一個(gè)交換機(jī)下的兩臺(tái)機(jī)器之間的Round Trip時(shí)間。VoltDB對(duì)于用戶每一次事務(wù)的調(diào)用分配一個(gè)時(shí)間戳,并且保證這個(gè)時(shí)間戳是全局有序的,雖然時(shí)間戳是由集群中的各臺(tái)機(jī)器獨(dú)自分配的,但是加上機(jī)器的序號(hào),可以保證(機(jī)器序號(hào),時(shí)間戳)的組合值是全局有序的。一臺(tái)服務(wù)器執(zhí)行事務(wù)之前,需要等待Round Trip時(shí)間后,如果其他機(jī)器沒有開始比自己更早的事務(wù),那么就執(zhí)行自己的事務(wù)。以這種方式保證集群內(nèi)多臺(tái)機(jī)器之間事務(wù)的有序。數(shù)據(jù)的多個(gè)副本的更新操作也都以相同的順序進(jìn)行修改,所有副本之間保證了一致性。
事務(wù)并發(fā)處理
為了充分發(fā)揮多核機(jī)器的性能,而又不引入多線程執(zhí)行事務(wù)的復(fù)雜性,VoltDB的數(shù)據(jù)分片規(guī)模是按照集群核數(shù)來劃分的。一臺(tái)物理機(jī)器上可能運(yùn)行多個(gè)VoltDB服務(wù)器進(jìn)程,每個(gè)進(jìn)程對(duì)應(yīng)于一個(gè)核,服務(wù)器進(jìn)程之間都是通過網(wǎng)絡(luò)進(jìn)行通信。在單個(gè)進(jìn)程內(nèi),只使用單線程,所有的事務(wù)執(zhí)行都是順序進(jìn)行的。
多個(gè)事務(wù)在多個(gè)服務(wù)器節(jié)點(diǎn)同時(shí)執(zhí)行,VoltDB保證如果事務(wù)之間有沖突,那么事務(wù)的執(zhí)行是完全隔離的,即達(dá)到SERIALIZABLE ISOLATION。VoltDB會(huì)事先分析好存儲(chǔ)過程之間的關(guān)系,如果兩個(gè)事務(wù)可能存在沖突,則不讓這兩個(gè)進(jìn)程在同一個(gè)時(shí)間執(zhí)行。
在VoltDB的并發(fā)處理中,每一個(gè)事務(wù)在執(zhí)行之前都要等待一個(gè)Round Trip時(shí)間,顯然會(huì)增加事務(wù)執(zhí)行的時(shí)延。這么做是為了確保別的節(jié)點(diǎn)沒有發(fā)起比這個(gè)事務(wù)更早的事務(wù),保證事務(wù)執(zhí)行的順序。在實(shí)現(xiàn)中,VoltDB用了另外一種優(yōu)化方法。例如A,B兩個(gè)節(jié)點(diǎn),分別要執(zhí)行事務(wù)1和2,A節(jié)點(diǎn)開始執(zhí)行事務(wù)1的時(shí)間是T1,如果A收到B發(fā)了事務(wù)2的執(zhí)行需求,并且T2 > T1,那么A節(jié)點(diǎn)可以確認(rèn)從B節(jié)點(diǎn)不會(huì)有更早的事務(wù)再發(fā)送過來,A節(jié)點(diǎn)就不必等Round Trip時(shí)間,可以直接執(zhí)行事務(wù)1。當(dāng)整個(gè)系統(tǒng)壓力比較大時(shí),這個(gè)優(yōu)化方法效果尤其明顯,事務(wù)的時(shí)延有效降低。
VoltDB還花了很大精力在處理事務(wù)之間的邏輯關(guān)系,盡可能對(duì)事務(wù)分門別類進(jìn)行處理,以期獲得更好的性能。
范圍查詢的處理
VoltDB取巧的采用的哈希的方法做數(shù)據(jù)分布,在面對(duì)范圍查詢的需求時(shí),再次吃到苦果。哈希方法打亂了數(shù)據(jù)的連續(xù)性,對(duì)于范圍查詢的處理能力顯著下降。VoltDB執(zhí)行某張表的范圍查詢,需要發(fā)送這個(gè)查詢到這張表的所有數(shù)據(jù)分片上。在所有分片完成同樣的范圍查詢,再將結(jié)果匯總,才能得到全局的準(zhǔn)確結(jié)果。所以VoltDB處理范圍查詢會(huì)很低效
數(shù)據(jù)持久化
雖然Stonebraker在H-Store的論文里反復(fù)提到,在內(nèi)存型數(shù)據(jù)庫(kù)里,即使使用Group Commit寫操作日志也是非常低效的,但是為了保證數(shù)據(jù)的持久性,VoltDB還是不得不采用記操作日志的辦法。VoltDB使用定期做Snapshot加上記操作日志來保證數(shù)據(jù)持久性,這種方法沒有什么特別的地方。
新聞熱點(diǎn)
疑難解答
圖片精選