轉自:http://www.lxweimin.com/p/23db015e81a5
github:https://github.com/linkedin/PalDB
簡介
PalDB是 Linkedin 公司開源的一款只讀型的 KV 存儲數據庫,目的是在某些場景下替代 HashMap/HashSet 或 LevelDB,在性能和內存之間做了一個良好的平衡。下面是官方給出的測試圖表:
讀的吞吐量是 leveldb 和 rocksdb 的5倍
內存使用是 hashset 的1/6
使用方式
作為一個存儲工具包,其使用方式也很簡單,一看就會明白:
//寫數據
StoreWriter writer = PalDB.createWriter(new File("store.paldb"));
writer.put("foo", "bar");
writer.put(1213, new int[] {1, 2, 3});
writer.close();
//讀數據
StoreReader reader = PalDB.createReader(new File("store.paldb"));
String val1 = reader.get("foo");
int[] val2 = reader.get(1213);
reader.close();
應用場景
PalDB 適合一次寫入,多次讀取,且數據量較大的場景,如:
Hadoop/Spark 計算時產生的一些中間結果
機器學習訓練出的模型
詞典
實現原理
PalDB 本質上是一個哈希表,用開放尋址法處理哈希沖突。下面從讀寫兩方面來分析其實現細節。
寫
寫數據的過程主要分為3塊:序列化,預寫入,最終寫入。
序列化:序列化過程主要負責將準備寫入的 key-value 值進行序列化。PalDB 自己實現了對 java 基本對象的序列化,對數據進行了一定的壓縮(如果覺得壓縮的仍不夠,PalDB 默認支持 Snappy 壓縮算法,可手動開啟)。
預寫入:程序每調用一次 writer.put(Object key, Object value) ,PalDB 就進行一次預寫入。預寫入負責寫兩類文件:
索引文件:存儲 key 以及 value 在數據文件中的位置
數據文件:存儲 value 長度以及 value
這兩類文件都有一個或者多個,成對出現,文件數量決于 key(序列化后)的長度,一個 key 長度對應一對<索引文件,數據文件>。也就是說,key 長度是一個一級索引,這個在讀的時候會用到。下面用一張圖總結下預寫入的過程。
預寫入工程
預寫入過程中還會記錄一些重要的值,如:value 位置的最大長度,key 總數以及每個 key 長度下的 key 數量。
3.最終寫入
當寫完數據最終調用 writer.close() 時就進入最終寫入階段。預寫入生成的索引文件只是順序的存儲了 key 以及 value 在數據文件中的位置,最終寫入階段負責將索引文件轉化成哈希表,跟索引文件一樣,每一個 key 長度對應一個哈希表。對每一個哈希表:
哈希表 slot 數量 = 該 key 長度下的 key 數量 / loadFactor(默認0.75,可手動指定)
每個 slot 的大小是固定的,等于 key 長度 +? value 位置的最大長度(因此,slot 里的數據其實是有部分空閑的)。
寫這個哈希表的過程是順序讀預寫入階段生成的索引文件,按 key? hash 到指定 slot(用開放尋址法處理哈希沖突)并寫入 key 以及 value 位置的過程。
遍歷處理完所有 key 長度對應的索引文件后,將所有哈希表、數據文件、meta 信息拼接,形成最終的數據庫文件。文件結構如下:
最終數據庫文件結構
讀
首先 PalDB 會將數據庫文件初始化,初始化過程分為三步:
讀取 meta 信息,如 key 數據,key 長度數量、每個 key 長度對應的索引文件 slot 數等,并存儲在內存中。
以一個只讀內存映射文件方式(MappedByteBuffer)打開 key 索引集合。由于 PalDB 將 key 索引集合當做一個文件打開,由于內存映射文件的大小限制,key 索引集合的大小不能超過 2G。
以一個或多個只讀內存映射文件方式打開數據文件集合。如果數據文件過大(大于2G),PalDB 會將其切分成多塊。
初始化完成后,就可以調用 reader.get(Object o) 方法進行數據讀取,數據讀取的流程如下:
讀取數據流程
總結
PalDB 的實現原理還是比較簡單的,但是在某些場景下效果會比常規方法更好。就筆者的實踐來說,用 PalDB 存儲推薦模型來代替之前的文件 load 到內存的方式,在性能影響很小的情況下大大減少了內存的使用,值得一試。
作者:兩棵橘樹
鏈接:http://www.lxweimin.com/p/23db015e81a5
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。