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