lightning mdb 源代碼分析(1)

lighting mdb(lmdb) 是一個高性能mmap kv數據庫,基本介紹和文檔參見symas官網,本文將嘗試分析其源代碼結構以理解數據庫設計的關鍵技術。node

本系列文章將嘗試從如下幾個方面進行分析。數據庫

  1. 系統架構(本文)
  2. MMAP映射(系列2)
  3. B+Tree操做(系列3)
  4. 事務管理(系列4)
  5. MVCC控制(系列5)

等幾個方面進行分析。後端

lmdb是爲了改進OPENLADP工程的數據緩存後端數據庫(bdb)的一系列設計問題,好比多重緩存設計、鎖控制、空間膨脹的問題而研發的一款數據庫。緩存

其具有管理簡單、開發簡單等特色。管理簡單是由於其設計中去掉了數據庫級緩存,開發簡單是兼容bdb開發接口,無需擔憂數據損壞、空間膨脹、死鎖等數據結構

問題。多線程

其系統基本架構爲:架構

image

設計上使用了mmap和COW技術,所以總體架構比較簡單,沒有其餘數據庫的緩存管理、日誌管理、外存管理等組件。app

mmap文件映射是基礎,lmdb經過只讀文件映射(默認)避免了由於應用程序bug致使數據庫被破壞的情形。其上的數據庫設計

一些基礎結構好比Locktables,MVCC,COW等都是實現事務控制的基礎,經過這些理論基礎,lmdb實現了完整的性能

ACI屬性,D經過mmap實現。最後,系統對外提供了關於B+Tree的操做方式,利用cursor遊標進行。能夠進行增刪改查。

B+Tree的全部變更方式與其餘的實現相似,不過lmdb的實現基礎是append only B+Tree,後續系列將詳細解釋lmdb裏面的

B+Tree實現方式。

主要的系統數據結構有:

1. MDB_ENV

image

2. mdb_envinfo

image

 

首先關鍵的是env對象,environment對象表明了一個實際的物理存儲文件。lmdb採起的存儲方式是直接B+Tree存儲,索引和值都存儲在B+Tree的

頁面上,對於值特別大的對象經過overflow頁面解決。而非像其餘存儲方式,索引與數據分離。可是lmdb存儲支持在同一個物理文件中存儲多個B+Tree,

以及能夠將某個B+Tree做爲另外一個B+Tree的葉子節點,即其提到的sub-database概念。這對於某些特定的應用比較有效,好比簡單的層次對應數據結構的

管理和查詢。

env對象中重要數據成員有:

me_dirty-list:髒頁列表,是寫事務已經修改過的但沒有提交到物理文件中的全部頁面列表。

me_free_pgs: 可用頁面,可用頁面用於控制MVCC致使的文件大小膨脹,可用頁面是指已經沒有事務使用可是已經被修改,根據MVCC原理,其已是舊版本的頁面。

對於須要查閱歷史數據的數據庫來講,好比說須要恢復到任意時刻的要求,全部的舊版本應該被保存,而對於只須要保持最新一致數據的數據庫系統好比lmdb來講,這些

頁面是能夠重用的,頁面重用就能夠有效避免物理文件的無限增大。free_pgs爲當前寫事務致使的可重用頁面列表。

me_metas: 元數據列表,lmdb使用兩個頁面做爲meta頁面,所以其大小爲2. meta頁面的一個主要做用是用於保存B+Tree的root_page指針。其內部採用COW技術,root

page指針可能會被修改,所以使用兩個不一樣的頁面進行切換保存最新頁面,相似於double-buffer設計。由此可知,雖然lmdb支持一個文件中多個B+Tree,因爲meta頁面的

限制,其個數是有限的。

me_rmutext,me_wmutex: 鎖表互斥所,lmdb能夠支持多線程、多進程。多進程之間的同步訪問經過系統級的互斥來達到。其mutex自己存在於系統的共享內存當中而非進程自己的內存,所以

在進行讀寫頁面時,首先訪問鎖表看看對應的資源是否有別的進程、線程在進行,有的話須要根據事務規則要求進行排隊等待。詳細的鎖使用見後文解釋。

me_txn,me_txns: 目前環境中使用的事務列表,一個env對象歸屬於一個進程,一個進程可能有多個線程使用同一個env,每一個線程能夠開啓一個事務,所以在一個進程級的env對象須要維護txn列表

以瞭解目前多少個線程及事務在進行工做。

me_flags: 標誌,標誌控制的數據庫的許多行爲,每次使用env以前必須設置,應用程序應該用一致的方式使用flags,不然數據庫可能會出現不可預知的錯誤。

me_dbxs: 數據庫對象

me_userctx: 用戶數據,用戶上下文數據,主要用於進行key比較時進行輔助。

 

envinfo對象中成員比較直白,很少囉嗦。

 

3. mdb_meta

image

meta頁的更新由事務id決定,讀事務不更新元數據頁,寫數據可能更新。

meta頁面循環使用,即id爲1,修改頁面1,id爲2,修改頁面0.

其最重要的數據成員就是

mm_dbs: 數據庫B+Tree根,同時保存兩個,0爲目前使用的可替代的root page指針,1爲當前使用的主數據庫。

mm_version: 當前lock文件的version,是實現MVCC的重要成員,必須設置爲MDB_DATA_VERSION.

4. MDB_PAGE

image

page描述了不一樣頁面的頭。不論是樹中的root、仍是branch、leaf頁面,都是用它描述。

對於overflow頁面來講,只有第一頁使用頭進行描述,其後的連續頁面不使用,僅僅使用指針

將頁面關聯起來。

重要成員:

mp_flags: 表明是什麼類型的頁面

mp_pb: overflow頁數或者當前頁的可用空間

5.MDB_NODE

image

node表明key/value對的描述,是對branch、leaf頁中的數據的描述

重要成員包括:

mn_flags: 標誌:是否重複、子數據庫、overflow等

mn_hi.lo: 數據大小或者頁碼

mn_data:數據指針

6. MDB_DB

image

mdb_db描述了一顆單獨的b+tree數,主要包含了一些相關的信息和根節點頁碼

7. MDB_TXN

image

mdb_txn描述了事務的數據結構,mdb中的事務支持嵌套事務。支持徹底ACID屬性,

可是隻支持serializable事務隔離級別,經過同一個env對應的數據庫只容許一個事務寫來控制。

事務的操做方式與其餘數據庫相似,嵌套事務必須匹配。

其重要的成員包括:

mt_child,parent:事務嵌套父子關係

mt_next_pgno: 未分配的頁面id

mt_cursor: 寫事務中每一個數據庫中已經打開的遊標。

8. MDB_Cursor

image

遊標對象是進行全部數據庫操做的對象,讀寫都是基於遊標進行。進行讀寫操做時,首先須要根據條件

肯定頁面位置,從而得到一個遊標,應用程序根據遊標對象操做數據庫。

其重要成員有:

mc_next: 同一個事務中關於同一個db的遊標組成一個列表。next指向下一個遊標

mc_top: 最上層頁面id

mc_xcursor: 用於key可重複b+tree。

mc_pg: cursor打開的頁面組成一個堆棧,最多32個,具體做用還有待探查。

mc_ki:  全部打開頁面的索引

 

本文簡單講述了lmdb的總體架構以及重要的數據成員。本系列下次介紹MMAP原理以及

其在lmdb中的使用方式

相關文章
相關標籤/搜索