引子
VoltDB是一個宣稱性能超過Mysql 100倍的新型數據庫。它源自Micheal Stonebraker一篇論文H-Store。在這篇論文發表后,Stonebraker成立了VoltDB公司帶著他的一些學生開始在OLTP數據庫領域打拼。Stonebraker從上世紀70年代——數據庫剛開始發展的時間——就開始在數據庫領域活躍,這樣的老古董提出的數據庫的新想法,給了整個存儲領域很大的想象空間。
VoltDB源起于應用領域與硬件發展翻天覆地的變化。用戶的使用方法發生了變化,在數據庫開始發展的階段,事務是一個較長的過程,用戶或者管理員可以在”BEGIN TRANSACTION”和”END TRANSACTION”之間慢慢地人工執行整個事務的步驟。但是現在,大部分操作是由Web服務端發起的書寫良好的事務,用戶訪問的是Web服務器,在Web服務器的執行邏輯里再訪問數據庫,所以即使是很復雜的事務也可以很快執行完。計算機硬件的發展更是一日千里。幾十GB的內存服務器已經很常見。以太網絡也已經步入Gbps時代,而且正在朝向10Gbps方向邁進?;谝蕴W的集群的機器價格也降低到比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的事務并發控制需要依賴于集群內所有機器的時間是一致的,這個可以使用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加上記操作日志來保證數據持久性,這種方法沒有什么特別的地方。
新聞熱點
疑難解答