日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

PalDB 详解

發(fā)布時(shí)間:2025/3/18 编程问答 14 豆豆
生活随笔 收集整理的這篇文章主要介紹了 PalDB 详解 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

轉(zhuǎn)自:http://www.jianshu.com/p/23db015e81a5

github:https://github.com/linkedin/PalDB


簡介

PalDB是 Linkedin 公司開源的一款只讀型的 KV 存儲(chǔ)數(shù)據(jù)庫,目的是在某些場(chǎng)景下替代 HashMap/HashSet 或 LevelDB,在性能和內(nèi)存之間做了一個(gè)良好的平衡。下面是官方給出的測(cè)試圖表:

讀的吞吐量是 leveldb 和 rocksdb 的5倍

內(nèi)存使用是 hashset 的1/6

使用方式

作為一個(gè)存儲(chǔ)工具包,其使用方式也很簡單,一看就會(huì)明白:

//寫數(shù)據(jù)

StoreWriter writer = PalDB.createWriter(new File("store.paldb"));

writer.put("foo", "bar");

writer.put(1213, new int[] {1, 2, 3});

writer.close();

//讀數(shù)據(jù)

StoreReader reader = PalDB.createReader(new File("store.paldb"));

String val1 = reader.get("foo");

int[] val2 = reader.get(1213);

reader.close();

應(yīng)用場(chǎng)景

PalDB 適合一次寫入,多次讀取,且數(shù)據(jù)量較大的場(chǎng)景,如:

Hadoop/Spark 計(jì)算時(shí)產(chǎn)生的一些中間結(jié)果

機(jī)器學(xué)習(xí)訓(xùn)練出的模型

詞典

實(shí)現(xiàn)原理

PalDB 本質(zhì)上是一個(gè)哈希表,用開放尋址法處理哈希沖突。下面從讀寫兩方面來分析其實(shí)現(xiàn)細(xì)節(jié)。

寫數(shù)據(jù)的過程主要分為3塊:序列化,預(yù)寫入,最終寫入。

序列化:序列化過程主要負(fù)責(zé)將準(zhǔn)備寫入的 key-value 值進(jìn)行序列化。PalDB 自己實(shí)現(xiàn)了對(duì) java 基本對(duì)象的序列化,對(duì)數(shù)據(jù)進(jìn)行了一定的壓縮(如果覺得壓縮的仍不夠,PalDB 默認(rèn)支持 Snappy 壓縮算法,可手動(dòng)開啟)。

預(yù)寫入:程序每調(diào)用一次 writer.put(Object key, Object value) ,PalDB 就進(jìn)行一次預(yù)寫入。預(yù)寫入負(fù)責(zé)寫兩類文件:

索引文件:存儲(chǔ) key 以及 value 在數(shù)據(jù)文件中的位置

數(shù)據(jù)文件:存儲(chǔ) value 長度以及 value

這兩類文件都有一個(gè)或者多個(gè),成對(duì)出現(xiàn),文件數(shù)量決于 key(序列化后)的長度,一個(gè) key 長度對(duì)應(yīng)一對(duì)<索引文件,數(shù)據(jù)文件>。也就是說,key 長度是一個(gè)一級(jí)索引,這個(gè)在讀的時(shí)候會(huì)用到。下面用一張圖總結(jié)下預(yù)寫入的過程。

預(yù)寫入工程

預(yù)寫入過程中還會(huì)記錄一些重要的值,如:value 位置的最大長度,key 總數(shù)以及每個(gè) key 長度下的 key 數(shù)量。

3.最終寫入

當(dāng)寫完數(shù)據(jù)最終調(diào)用 writer.close() 時(shí)就進(jìn)入最終寫入階段。預(yù)寫入生成的索引文件只是順序的存儲(chǔ)了 key 以及 value 在數(shù)據(jù)文件中的位置,最終寫入階段負(fù)責(zé)將索引文件轉(zhuǎn)化成哈希表,跟索引文件一樣,每一個(gè) key 長度對(duì)應(yīng)一個(gè)哈希表。對(duì)每一個(gè)哈希表:

哈希表 slot 數(shù)量 = 該 key 長度下的 key 數(shù)量 / loadFactor(默認(rèn)0.75,可手動(dòng)指定)

每個(gè) slot 的大小是固定的,等于 key 長度 +? value 位置的最大長度(因此,slot 里的數(shù)據(jù)其實(shí)是有部分空閑的)。

寫這個(gè)哈希表的過程是順序讀預(yù)寫入階段生成的索引文件,按 key? hash 到指定 slot(用開放尋址法處理哈希沖突)并寫入 key 以及 value 位置的過程。

遍歷處理完所有 key 長度對(duì)應(yīng)的索引文件后,將所有哈希表、數(shù)據(jù)文件、meta 信息拼接,形成最終的數(shù)據(jù)庫文件。文件結(jié)構(gòu)如下:

最終數(shù)據(jù)庫文件結(jié)構(gòu)

首先 PalDB 會(huì)將數(shù)據(jù)庫文件初始化,初始化過程分為三步:

讀取 meta 信息,如 key 數(shù)據(jù),key 長度數(shù)量、每個(gè) key 長度對(duì)應(yīng)的索引文件 slot 數(shù)等,并存儲(chǔ)在內(nèi)存中。

以一個(gè)只讀內(nèi)存映射文件方式(MappedByteBuffer)打開 key 索引集合。由于 PalDB 將 key 索引集合當(dāng)做一個(gè)文件打開,由于內(nèi)存映射文件的大小限制,key 索引集合的大小不能超過 2G。

以一個(gè)或多個(gè)只讀內(nèi)存映射文件方式打開數(shù)據(jù)文件集合。如果數(shù)據(jù)文件過大(大于2G),PalDB 會(huì)將其切分成多塊。

初始化完成后,就可以調(diào)用 reader.get(Object o) 方法進(jìn)行數(shù)據(jù)讀取,數(shù)據(jù)讀取的流程如下:

讀取數(shù)據(jù)流程

總結(jié)

PalDB 的實(shí)現(xiàn)原理還是比較簡單的,但是在某些場(chǎng)景下效果會(huì)比常規(guī)方法更好。就筆者的實(shí)踐來說,用 PalDB 存儲(chǔ)推薦模型來代替之前的文件 load 到內(nèi)存的方式,在性能影響很小的情況下大大減少了內(nèi)存的使用,值得一試。

作者:兩棵橘樹

鏈接:http://www.jianshu.com/p/23db015e81a5

來源:簡書

著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。

總結(jié)

以上是生活随笔為你收集整理的PalDB 详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。