VoltDB內存資料庫分析

VoltDB內存數據庫分析

來源:https://blog.csdn.net/olidrop/article/details/7065384

引子

VoltDB是一個宣稱性能超過Mysql 100倍的新型數據庫。它源自Micheal Stonebraker一篇論文H-Store。在這篇論文發表後,Stonebraker成立了VoltDB公司帶著他的一些學生開始在OLTP數據庫領域打拼。Stonebraker從上世紀70年代——數據庫剛開始發展的時間——就開始在數據庫領域活躍,這樣的老古董提出的數據庫的新想法,給了整個存儲領域很大的想象空間。

VoltDB源起於應用領域與硬件發展翻天覆地的變化。用戶的使用方法發生了變化,在數據庫開始發展的階段,事務是一個較長的過程,用戶或者管理員可以在"BEGIN TRANSACTION"和"END TRANSACTION"之間慢慢地人工執行整個事務的步驟。但是現在,大部分操作是由Web服務端發起的書寫良好的事務,用戶訪問的是Web服務器,在Web服務器的執行邏輯裡再訪問數據庫,所以即使是很複雜的事務也可以很快執行完。計算機硬件的發展更是一日千里。幾十GB的內存服務器已經很常見。以太網絡也已經步入Gbps時代,而且正在朝向10Gbps方向邁進。基於以太網的集群的機器價格也降低到比PC機貴不了太多。VoltDB的設計充分利用了這些特點,數據主要存儲在內存中,Shared Nothing的集群結構,單機是單線程處理事務,不是用鎖而是基於Optimistic的方法處理事務併發,所有的事務必須以存儲過程形式先提交到VoltDB系統。下面分開來說。

事務提交

既需要支持複雜的事務操作,又需要快速的執行過程,VoltDB採取了一個比較極端的事務提交方式。雖然VoltDB支持部分SQL語句接口,但是不允許用戶使用傳統的"BEGIN TRANSACTION"和"END TRANSACTION"的語法模式,而是完全基於存儲過程。用戶通過寫存儲過程完成應用程序的邏輯,作為一個先置條件將存儲過程提交到VoltDB。運行時,用戶程序調用存儲過程完成事務操作,所有事務的運行邏輯是由VoltDB在服務器進程中完成的。這種方式保證了事務不會被人為打斷,並且服務器可以預先判斷各個事務的邏輯,也為事務併發處理挖掘信息。

數據分佈

VoltDB使用Shared Nothing結構,整個數據庫的數據分散到集群的多臺機器上。VoltDB的數據分佈策略是基於哈希的,存儲在VoltDB中的每一張表,對數據的主鍵哈希取模後的結果對應於數據存儲的節點。相比較於BigTable基於主鍵的連續範圍分段的方法,哈希方法的好處是數據分散的均勻,沒有動態數據調整的煩惱。但也有很多缺點,採用這種方法後,集群的規模是事先確定好的,新增機器需要停止服務後重新分佈數據。另外,數據哈希被分散後,數據的連續性被打亂了,在這個數據結構上做範圍查詢需要動用服務這張表的所有機器,這個後面會祥說。

VoltDB內存數據庫分析

上面這張圖描述了數據的分佈方式,VoltDB集群的每臺機器都會服務多張表。從圖裡還能看到VoltDB的數據複製是基於機器單位的,藍色框圈住的兩臺機器內的數據是完全同構的。

VoltDB的哈希分佈數據的方法是系統設計的簡化,這種簡化讓VoltDB工程實現難度降低,可以快速的商用。天下沒有免費的午餐,這個設計也是VoltDB功能缺陷,導致VoltDB無法動態擴容以及其他一些問題。

數據一致性

同一份數據的多個副本之間需要保證數據一致性,VoltDB採用所有修改操作在每一個副本上單獨更新的方式。如何保證更新操作在所有副本上以相同的順序更改而不至於產生不一致,這就要提到VoltDB的併發控制方式。

VoltDB的事務併發控制需要依賴於集群內所有機器的時間是一致的,這個可以使用NTP之類的時間同步協議,保證機器之間的時間差異遠遠小於一個交換機下的兩臺機器之間的Round Trip時間。VoltDB對於用戶每一次事務的調用分配一個時間戳,並且保證這個時間戳是全局有序的,雖然時間戳是由集群中的各臺機器獨自分配的,但是加上機器的序號,可以保證(機器序號,時間戳)的組合值是全局有序的。一臺服務器執行事務之前,需要等待Round Trip時間後,如果其他機器沒有開始比自己更早的事務,那麼就執行自己的事務。以這種方式保證集群內多臺機器之間事務的有序。數據的多個副本的更新操作也都以相同的順序進行修改,所有副本之間保證了一致性。

事務併發處理

為了充分發揮多核機器的性能,而又不引入多線程執行事務的複雜性,VoltDB的數據分片規模是按照集群核數來劃分的。一臺物理機器上可能運行多個VoltDB服務器進程,每個進程對應於一個核,服務器進程之間都是通過網絡進行通信。在單個進程內,只使用單線程,所有的事務執行都是順序進行的。

多個事務在多個服務器節點同時執行,VoltDB保證如果事務之間有衝突,那麼事務的執行是完全隔離的,即達到SERIALIZABLE ISOLATION。VoltDB會事先分析好存儲過程之間的關係,如果兩個事務可能存在衝突,則不讓這兩個進程在同一個時間執行。

在VoltDB的併發處理中,每一個事務在執行之前都要等待一個Round Trip時間,顯然會增加事務執行的時延。這麼做是為了確保別的節點沒有發起比這個事務更早的事務,保證事務執行的順序。在實現中,VoltDB用了另外一種優化方法。例如A,B兩個節點,分別要執行事務1和2,A節點開始執行事務1的時間是T1,如果A收到B發了事務2的執行需求,並且T2 > T1,那麼A節點可以確認從B節點不會有更早的事務再發送過來,A節點就不必等Round Trip時間,可以直接執行事務1。當整個系統壓力比較大時,這個優化方法效果尤其明顯,事務的時延有效降低。

VoltDB還花了很大精力在處理事務之間的邏輯關係,儘可能對事務分門別類進行處理,以期獲得更好的性能。

範圍查詢的處理

VoltDB取巧的採用的哈希的方法做數據分佈,在面對範圍查詢的需求時,再次吃到苦果。哈希方法打亂了數據的連續性,對於範圍查詢的處理能力顯著下降。VoltDB執行某張表的範圍查詢,需要發送這個查詢到這張表的所有數據分片上。在所有分片完成同樣的範圍查詢,再將結果彙總,才能得到全局的準確結果。所以VoltDB處理範圍查詢會很低效

數據持久化

雖然Stonebraker在H-Store的論文裡反覆提到,在內存型數據庫裡,即使使用Group Commit寫操作日誌也是非常低效的,但是為了保證數據的持久性,VoltDB還是不得不採用記操作日誌的辦法。VoltDB使用定期做Snapshot加上記操作日誌來保證數據持久性,這種方法沒有什麼特別的地方。


分享到:


相關文章: