在介紹 NoSQL 之前, 我想提兩個公司, 一個是Google, 另一個是Amazon。
Google 應該是第一個將分散式存儲技術應用到大規模生產環境的公司, 同時也是在分散式系統上積累最深的公司, 可以說目前工業界的分散式系統的工程實踐及思想大都來源於 Google。 比如 2003 年的 GFS 開創了分散式檔案系統, 2006 年的 Bigtable 論文開創了分散式鍵值系統, 直接催生的就是 Hadoop 的生態;至於 2012 年發表論文的Spanner和F1更是一個指明未來關係型數據庫發展方向的里程碑式的項目, 這個我們後續會說。
Amazon
另一個公司是 Amazon。 2007 年發表的Dynamo的論文嘗試引入了最終一致性的概念, WRN 的模型及向量時鐘的應用,
新思潮
另外這個時期(2006 年前後持續至今)一個比較重要的思潮就是資料庫(持久化)和緩存開始有明確的分離——我覺得這個趨勢是從 memcached 開始的。
這是因為 NoSQL 的另外一個重要的標誌——資料模型的變化——大多 NoSQL 都拋棄了關係模型, 選擇更簡單的鍵值或者文檔類型進行存儲。 資料結構和查詢介面都相對簡單, 沒有了SQL 的包袱, 實現的難度會降低很多。
另外 NoSQL 的設計幾乎都選擇犧牲掉複雜 SQL 的支援及 ACID 事務換取彈性擴展能力, 也是從當時互聯網的實際情況出發:業務模型簡單、爆發性增長帶來的海量併發及資料總量爆炸、歷史包袱小、工程師強悍,
嵌入式存儲引擎
在開始介紹具體的開源的完整方案前, 我想介紹一下嵌入式存儲引擎們。
隨著 NoSQL 的發展, 不僅僅緩存和持久化存儲開始細分, 再往後的存儲引擎也開始分化並走上前臺。 之前很難想像一個存儲引擎獨立於資料庫直接對外提供服務, 就像你不會直接拿著 InnoDB 或者 MyISAM甚至一個 B-tree 出來用一樣(當然, bdb 這樣鼎鼎大名的除外)。 人們基於這些開源的存儲引擎進行進一步的封裝, 比如加上網路通訊協定層、加上複製機制等等, 一步步構建出完整的風格各異的 NoSQL 產品。
這裡我挑選幾個比較著名存儲引擎介紹一下。
TC
我最早接觸的是Tokyo Cabinet(TC)。 TC 相信很多人也都聽說過, TC 是由日本最大的社交網站 Mixi 開發並開源的一個混合 Key-Value 存儲引擎, 其中包括 HASH Table 和 B+ Tree 的實現。 但是這個引擎的一個缺陷是隨著資料量的膨脹, 性能的下降會非常明顯, 而且現在也基本不怎麼維護了, 所以入坑請慎重。 於 TC 配合使用的Tokyo Tyrant(TT)是一個網路庫, 為 TC 提供網路的介面使其變成一個資料庫服務, TT + TC 應該是比較早的 NoSQL 的一個嘗試。
LevelDB
在 2011 年, Google 開源了 Bigtable 的底層存儲擎:LevelDB。 LevelDB 是一個使用 C++ 開發的嵌入式的 Key-Value 存儲引擎, 資料結構採用了 LSM-Tree, 具體 LSM-Tree 的演算法分析可以很容易在網上搜索到, 我就不贅述了。 其特點是, 對於寫入極其友好, LSM 的設計避免了大量的隨機寫入;對於特定的讀也能達到不錯的性能(熱資料在記憶體中);另外 LSM-Tree 和 B-tree 一樣是支持有序 Scan 的;而且 LevelDB 是出自 Jeff Dean 之手,
LevelDB 擁有極好的寫性能, 執行緒安全, BaTCh Write 和 Snapshot 等特性, 使其很容易的在上層構建 MVCC 系統或者事務模型, 對於資料庫來說非常重要。
另外值得一說的是,Facebook 維護了一個活躍的 LevelDB 的分支,名為 RocksDB。RocksDB 在 LevelDB 上做了很多的改進,比如多執行緒 Compactor、分層自訂壓縮、多 MemTable 等。另外 RocksDB 對外暴露了很多 Configration ,可以根據不同業務的形態進行調優;同時 Facebook 在內部正在用 RocksDB 來實現一個全新的 MySQL 存儲引擎:MyRocks,值得關注。RocksDB 的社區回應速度很快也很友好,實際上 PingCAP 也是 RocksDB 的社區貢獻者。我建議新的項目如果在 LevelDB 和 RocksDB 之間糾結的話,請果斷選擇 RocksDB。
B-tree 家族
當然,除了 LSM-Tree 外,B-tree的家族也還是有很多不錯的引擎。首先大多數傳統的單機資料庫的存儲引擎都選擇了B+Tree,B+Tree 對磁片的讀比較友好,協力廠商存儲引擎比較著名的純 B+Tree 實現是LMDB。首先 LMDB 選擇在記憶體映射檔 (mmap) 實現 B+Tree,同時使用了 Copy-On-Write 實現了 MVCC 實現併發事務無鎖讀的能力,對於高併發讀的場景比較友好;同時因為使用的是 mmap 所以擁有跨進程讀取的能力。因為我並沒有在生產環境中使用過 LMDB ,所以並不能給出 LMDB 的一些缺陷,見諒。
另外值得一說的是,Facebook 維護了一個活躍的 LevelDB 的分支,名為 RocksDB。RocksDB 在 LevelDB 上做了很多的改進,比如多執行緒 Compactor、分層自訂壓縮、多 MemTable 等。另外 RocksDB 對外暴露了很多 Configration ,可以根據不同業務的形態進行調優;同時 Facebook 在內部正在用 RocksDB 來實現一個全新的 MySQL 存儲引擎:MyRocks,值得關注。RocksDB 的社區回應速度很快也很友好,實際上 PingCAP 也是 RocksDB 的社區貢獻者。我建議新的項目如果在 LevelDB 和 RocksDB 之間糾結的話,請果斷選擇 RocksDB。
B-tree 家族
當然,除了 LSM-Tree 外,B-tree的家族也還是有很多不錯的引擎。首先大多數傳統的單機資料庫的存儲引擎都選擇了B+Tree,B+Tree 對磁片的讀比較友好,協力廠商存儲引擎比較著名的純 B+Tree 實現是LMDB。首先 LMDB 選擇在記憶體映射檔 (mmap) 實現 B+Tree,同時使用了 Copy-On-Write 實現了 MVCC 實現併發事務無鎖讀的能力,對於高併發讀的場景比較友好;同時因為使用的是 mmap 所以擁有跨進程讀取的能力。因為我並沒有在生產環境中使用過 LMDB ,所以並不能給出 LMDB 的一些缺陷,見諒。