現實世界有許多的Key-Value數據庫,它們都被廣泛應用于很多系統。比如,我們能夠用Memcached數據庫存儲一個MySQL查詢結果集給后續相同的查詢使用,用MongoDB存儲文檔以得到更好的查詢性能等等。
針對不同的場景,我們應該選不同的Key-Value數據庫,沒有一個Key-Value數據庫適用于所有解決方案,但是如果你僅僅想要一個簡單、易于使用、快速、支持多種強大數據結構的Key-Value數據庫,Redis可能是你作為開始的一個很好的選擇。
Redis是一個先進的Key-Value緩存和數據庫,它基于BSD許可證。它的速度很快,支持許多數據類型(String、Hash、List、Set、Sorted Set……),使用RDB或AOF持久化和復制來保證數據的安全性,并且支持多種語言的客戶端庫。
重要的是市場選擇了Redis,有許多公司正在使用Redis并且它證明了自身的價值。
雖然redis是相當不錯的,它仍然有一些缺點,大的缺點就是內存限制,Redis將所有數據駐留內存,這就限制了整個數據集的大小,讓我們不可能保存更多的數據。
官方的Redis集群通過將數據分發到多個Redis服務器來解決這個問題,但是這個方法并沒有在許多實際環境中被證明。同時,它需要我們改變自己的客戶端庫來支持“MOVED”重定向和其它特殊命令,而這在正在運行的生產環境同樣是不可接受的。所以,Redis集群現在看來并不是一個好的解決方案。
我們喜歡Redis,并且希望超越它的局限,因此我們創建了一個服務叫做QDB,它兼容Redis,將數據保存在磁盤來越過內存大小的限制并且將熱點數據保存在內存中以提高性能。
介紹
QDB是一個類似Redis的快速Key-Value數據庫,它有以下優點:
兼容Redis:如果你對 Redis很熟悉,你就能輕松使用QDB,它支持大多數的Redis命令和數據結構(String、Hash、List、Set、Sorted Set等);
將數據保存在磁盤:(超越內存大小限制)可以將熱點數據在內存中保存,利用了后端存儲;
支持多種后端存儲:你可以選擇 RocksDB、LevelDB 或者 GoLevelDB(稍后,我們將用RocksDBs作為例子講解);
和Redis雙向同步:我們可以作為一個從節點從 Redis同步數據,也可以作為一個主節點復制數據到Redis。
后端存儲
QDB使用LevelDB、RocksDB、GoLevelDB作為后端存儲。這些存儲都是基于有著很好的快速讀寫性能的日志結構的合并樹(LSM樹),同時他們都使用布隆過濾器和LRU緩存(LRU:少使用頁面置換算法)來提高讀的性能。
LevelDB是由Google開發的早的版本,RocksDB是由Facebook維護的一個優化版本,GoLevelDB是一個純粹用GO語言實現的LevelDB。如果你僅僅想要一個快速試驗并且不想構建和安裝RocksDB或者LevelDB,你可以直接使用GoLevelDB,但是我們不推薦你將其使用在生產環境中,因為它的性能比較差。
LevelDB和RocksDB對于你的生產環境來說都是非常不錯的,但是鑒于RocksDB絕佳的性能,我們更喜歡RocksDB,之后我們將只支持RocksDB和GoLevelDB,一個用于生產環境,另一個用于試驗和測試環境中。
QDB是很棒的,我們能夠在一個機器上存儲巨大的數據,并且獲得較好的讀寫性能,但是隨著數據集的增長,我們仍然會面臨這樣的問題,即:我們不能將所有數據都保存在一個機器上。同時,QDB服務器將變成一個瓶頸并且面臨單點失敗的風險。
現在我們必須要考慮集群解決方案了。
RebornDB是一個基于代理的分布式Redis集群解決方案。它有點像twemproxy,一個幾乎是早的、的基于代理的Redis集群解決方案。
但是twemproxy有它自己的問題,它僅僅支持靜態的集群拓撲,因此我們不能動態的添加或者刪除redis節點來重新切分數據。如果我們運行著許多的twemproxy并且希望添加一個Redis后端節點,另一個問題是如何讓所有的twemproxy安全的更新配置,而這將增加IT操作的復雜性。同時,Twitter(正在開發twemproxy的公司)目前已經放棄并不再將其應用于生產環境。
不同于twemproxy,RebornDB有一個殺手锏:動態的切分數據集,這將非常有用,特別是在你的數據集增長很快,你不得不增加更多的存儲節點來擴展集群的情況下??傊?,RebornDB將會透明的重新切分數據而不影響目前正在運行的服務。
我們可以將RebornDB想象成一個黑盒,像一個單節點的Redis服務器一樣用任何現有的Redis客戶端去和它通信。下面的圖片展示了RebornDB的架構。

RebornDB有以下組件: reborn-proxy, backend store, coordinator, reborn-config, and reborn-agent.
Reborn-proxy
reborn-proxy為客戶端提供單一的外部服務。任何redis客戶端都能連接到任一reborn-proxy并運行命令。
reborn-proxy用RESP解析來自客戶端的命令,將其分發至對應的后端存儲,接收到后端存儲的答復并返回客戶端。
Reborn-proxy 是無狀態的,意思是說你可以很容易的水平擴展redis-proxy來處理更多的服務請求。
我們可以有許多的Reborn-proxy,在分布式系統設計的時候怎么讓客戶端發現它們是另一個主題,但是我們不會在這里深入探討這個問題,一些實用的方法是使用DNS,LVS,HAProxy等等。
后端存儲器(Backend store )
后端存儲器是reborn-server(一個修改的redis版本)或者QDB。我們引入一個概念叫做組(group)來管理一個或者多個后端存儲。一個組(group)必須有一個主節點和零個、一個或者多個從節點形成復制拓撲結構。
我們將整個數據集分成1024個slots(我們用hash(key)24來決定這個key屬于哪個slot),并且將不同的slot保存到不同的組。如果你想重新切分數據,你可以增加一個新的組并讓RebornDB 從另一個 組遷移一個slot的所有數據到新的組。
我們也可以讓不同的組采用不同的后端存儲器。例如:我們希望group1來保存熱點數據,group2來保存大量的冷數據,那么我們就能使用reborn-server構成group1,QDB構成group2.Reborn-server比QDB快很多,因此我們能夠保證熱點數據的讀寫性能。
協調器(Coordinator )
我們使用zookeeper或者etcd作為協調服務器,當我們需要做一些寫操作的時候,例如重新切分,故障轉移等,它們會協調所有的服務。
所有RebornDB的信息都被保存在協調器中,例如關鍵路由規則,reborn-proxy可以根據它將命令正確的分發至后端存儲器。
Reborn-config
Reborn-config是一個管理工具,我們可以使用它增加或刪除組,例如增加或刪除組中的存儲,從一個組遷移數據至另一個組等等。
如果我們想要改變RebornDB集群的信息,就必須使用Reborn-config。例如:我們不能直接使用“SLAVE NO ONE”命令將后端存儲器提升為主節點,而必須使用“reborn-config server promote groupid server”我們必須不僅僅改變組內的復制拓撲結構,而且要更新協調器中的信息,而這些只有Reborn-config能夠做到。
Reborn-config也提供了一個網站服務,因此你可以很容易的管理RebornDB,如果需要更多的控制,你可以使用它的HTTP RESTFUL API。
Reborn-agent
Reborn-agent是一個高可用組件。你可以用它啟動和停止應用(reborn-config, qdb-server, reborn-server, reborn-proxy)。我們將在接下來的高可用部分詳細討論。
RebornDB支持動態的重新切分數據。我們是怎么做到的呢?
正如我們上面說的,我們將整個數據集分成1024個slots,并且將不同的slot保存到不同的組。當我們新增加一個組的時候,我們會將一些slots從舊的組遷移到新組中。在重新切分過程中我們將它叫做遷移。在RebornDB中小的遷移單元是slot。
讓我們從下面的一個簡單的例子開始:

我們有兩個組,group1有兩個slot 1和2,group2有三個slot 3、4、5.現在group2的工作量比較大,我們將會增加group3并將slot5遷移進去。
我們可以使用下面的命令來將slot5從group2遷移至group3。
(譯者注:原文為 reborn-config slot migrate 5 5 3有誤)
這個命令看起來很簡單,但是我們需要在內部做很多工作來保證遷移的安全性。我們必須使用兩階段提交協議(2PC)來告訴reborn-proxy我們將把slot5從group2遷移至group3。待所有reborn-proxy確認并且答復之后,我們將開始遷移操作。
遷移的流程比較簡單:從slot5中得到一個key,從group2遷移它的數據至group3,然后刪除group2中的key,如此循環。后group2中就沒有slot5的數據而所有slot5的數據都在group3中。
key的遷移是原子性的,因此無論這個key之前是否在group2或者group3中,我們能夠確定的是在執行遷移命令之后它是在group3中的。
如果在group2中沒有數據是屬于slot5的,我們將停止遷移,拓撲結構看起來是下面這個樣子:

RebornDB使用reborn-agent來提供HA解決方案。
reborn-agent每時每刻都在檢查它啟動的應用是否是活動的,如果reborn-agent發現一個應用掛掉了,它會重新啟動這個應用。
Reborn-agent有點像一個管理員,但是它有更多的特點。
Reborn-agent提供HTTP Restful API方便我們添加或刪除需要被動態監控的應用程序。例如:我們能夠使用HTTP “/api/start_redis” API來啟動一個新的reborn-server,或者“/api/start_proxy” API來啟動一個新的reborn-proxy,我們也能夠用“/api/stop”來停止一個正在運行的應用并且從目前的監控列表中刪除它。
Reborn-agent不僅僅應用于本地應用的監控,同樣適用于后臺存儲的HA。多個Reborn-agent將首先通過協調器選擇一個主reborn-agent,它會不斷檢查后端存儲器是否是活動的,如果發現后端存儲器宕機了,它就會進行故障轉移。如果宕機的后端存儲器是一個從節點,reborn-agent將只會在協調器中將它設置為離線,但是如果它是主節點,reborn-agent將會從現有的從節點中選擇一個作為主節點并進行故障轉移操作。
盡管RebornDB有許多很棒的特性,我們仍然需要更多的工作去進一步提升它,我們后續可能做這些事情:
更好的用戶體驗:現在運行RebornDB并不是那么容易,我們將要做一系列工作諸如初始化slots、添加服務到group中、分配slots給一個組等等,在未來的工作中,如何降低用戶的使用門檻是我們必須要考慮的問題;
復制遷移:現在我們遷移是逐個key遷移slot,如果一個slot包含許多數據的話速度就不是很快,使用復制遷移可能會好很多。在上面的例子中,group2首先產生一個快照,group3 能夠在那個時間點取得所有slot5的數據,之后group3將從group2增量同步變化的數據。當我們發現group3取得了group2中slot5所有變化的數據之后,我們將進行切換,并從group2中刪除slot5;
精美的儀表板:為了提供更好的用戶體驗,我們希望通過儀表板控制和監控一切事務?;?nbsp;P2P的集群:現在RebornDB是一個基于代理的集群解決方案,我們可能重新設計整個架構,之后將使用P2P,就像官方redis集群一樣
構建一個分布式Key-value數據庫不是一件容易的事情,前方的路還很長,我們現在只是邁出了一小步。
如果你想要用一個像redis的、存儲更多數據、支持在分布式系統中動態切分數據的Key-value數據庫,RebornDB將是一個不錯的選擇。
本站文章版權歸原作者及原出處所有 。內容為作者個人觀點, 并不代表本站贊同其觀點和對其真實性負責,本站只提供參考并不構成任何投資及應用建議。本站是一個個人學習交流的平臺,網站上部分文章為轉載,并不用于任何商業目的,我們已經盡可能的對作者和來源進行了通告,但是能力有限或疏忽,造成漏登,請及時聯系我們,我們將根據著作權人的要求,立即更正或者刪除有關內容。本站擁有對此聲明的最終解釋權。