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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

从Bitcask存储模型谈超轻量级KV系统设计与实现

發布時間:2024/1/16 windows 33 coder
生活随笔 收集整理的這篇文章主要介紹了 从Bitcask存储模型谈超轻量级KV系统设计与实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Bitcask介紹

Bitcask是一種“基于日志結構的哈希表”(A Log-Structured Hash Table for Fast Key/Value Data)

Bitcask 最初作為分布式數據庫 Riak 的后端出現,Riak 中的每個節點都運行一個 Bitcask 實例,各自存儲其負責的數據。

拋開論文,我們先通過一篇博客 # Bitcask — a log-structured fast KV store 來了解bitcask的細節信息,下面是簡要的譯文。

Bitcask 設計

Bitcask 借鑒了大量來自日志結構文件系統和涉及日志文件合并的設計,例如 LSM 樹中的合并。它本質上是一個目錄,包含固定結構的追加日志文件和一個內存索引。內存索引以哈希表的形式存儲所有鍵及其對應的值所在數據文件中的偏移量和其他必要信息,用于快速查找到對應的條目。

數據文件

數據文件是追加日志文件,存儲鍵值對和一些元信息。一個 Bitcask 實例可以擁有多個數據文件,其中只有一個處于活動狀態,用于寫入,其他文件為只讀文件。

數據文件中的每個條目都有固定的結構,我們可以用類似下面的數據結構來描述:

struct log_entry {
    uint32_t crc;
    uint32_t timestamp;
    uint32_t key_size;
    uint32_t value_size;
    char key[key_size];
    char value[value_size];
};

鍵目錄(KeyDir)

鍵目錄是一個內存哈希表,存儲 Bitcask 實例中所有鍵及其對應的值所在數據文件中的偏移量和一些元信息,例如時間戳,可以用類似下面的數據結構來描述:

struct key_entry {
    uint32_t file_id;
    uint32_t offset;
    uint32_t timestamp;
};

寫入數據

將新的鍵值對存儲到 Bitcask 時,引擎首先將其追加到活動數據文件中,然后在鍵目錄中創建一個新條目,指定值的存儲位置。這兩個動作都是原子性的,意味著條目要么同時寫入兩個結構,要么都不寫入。

更新現有鍵值對

Bitcask 直接支持完全替換值,但不支持部分更新。因此,更新操作與存儲新鍵值對非常相似,唯一的區別是不會在鍵目錄中創建新條目,而是更新現有條目的信息,可能指向新的數據文件中的新位置。

與舊值對應的條目現在處于“游離狀態”,將在合并和壓縮過程中顯式地進行垃圾回收。

刪除鍵

刪除鍵是一個特殊的操作,引擎會原子性地將一個新的條目追加到活動數據文件中,其中值等于一個標志刪除的特殊值,然后從內存鍵目錄中刪除該鍵的條目。該標志值非常獨特,不會與現有值空間沖突。

讀取鍵值對

從存儲中讀取鍵值對需要引擎首先使用鍵目錄找到該鍵對應的數據文件和偏移量。然后,引擎從相應的偏移量處執行一次磁盤讀取,檢索日志條目。檢索到的值與存儲的校驗碼進行正確性檢查,然后將值返回給客戶端。

該操作本身非常快速,只涉及一次磁盤讀取和幾次內存訪問,但可以使用文件系統預讀緩存進一步提高速度。

合并和壓縮

正如我們在更新和刪除操作中看到的,與鍵關聯的舊條目保持原樣,處于“游離狀態”。這會導致 Bitcask 消耗大量磁盤空間。為了提高磁盤利用率,引擎會定期將較舊的已關閉數據文件壓縮成一個或多個新數據文件,其結構與現有數據文件相同。

合并過程遍歷 Bitcask 中所有只讀文件,生成一組數據文件,只包含每個存在的鍵的“最新”版本。

快速啟動

如果 Bitcask 發生故障并需要重啟,它必須讀取所有的數據文件并構建一個新的鍵目錄(KeyDir),如果沒有專門存儲,需要讀取所有文件重建。

其實上面的合并和壓縮操作可以部分緩解這個問題,一方面它們減少了需要讀取的最終會被廢棄的數據量,在合并的同事,可以生成一個hint提示文件,hint記錄了key和key指向的meta信息。 這樣讀取hint文件就可以快速重建鍵目錄(KeyDir)。

*Bitcask 評價

優點

  • 讀寫操作延遲低:Bitcask 的讀寫操作都非常快速,因為它只需要一次磁盤查找即可檢索任何值。
  • 高寫入吞吐量:Bitcask 的寫入操作是追加式的,并且不需要進行磁盤尋道,因此可以實現高寫入吞吐量。
  • 可預測的查找和插入性能:由于其簡單的設計,Bitcask 的查找和插入性能非常可預測,這對于實時應用程序非常重要。
  • 崩潰恢復快:Bitcask 的崩潰恢復速度很快,因為它只需要重建 KeyDir 即可。
  • 備份簡單:Bitcask 的備份非常簡單,只需復制數據文件目錄即可。

缺點

  • KeyDir 占用內存:KeyDir 需要將所有鍵存儲在內存中,這對系統的 RAM 容量提出了較高的要求,尤其是在處理大型數據集時。

解決方案

  • 分片:可以將鍵進行分片,將數據分布到多個 Bitcask 實例中,從而水平擴展系統并降低對內存的需求。這種方法不會影響基本的 CRUD(Create、Read、Update、Delete)操作。

為何要考慮自研輕量級KV系統

我們線上的搜索系統,檢索到match的doc后,需要通過id獲取doc的詳情,考慮到數據量級很大,redis首先排除,我們最初的選型是mongodb,在十億級別的數據量時,整體問題不大,但是面向未來更大的數據量級,我們需要考慮更容易維護的方案。

當前mongodb的問題:

  • mongodb的存儲滿了后,擴容較難
  • 每天增量數據寫入,影響讀取性能
  • 三地的集群,數據的一致性保障并非一件簡單的事情
  • 最重要的,我們的使用場景僅僅是kv查詢,mongodb在這個場景有點大材小用了

為了解決上面的問題,我們考慮一種數據分版本的方案。

具體來說,對于KV場景,將每個版本的數據,根據特定的hash規則將數據分成多片,每片離線按照Bitcask的思路,生成好hint文件和數據文件,上接一個分布式服務提供查詢即可。對于增量的數據,只需要按同樣的hash規則,先生成好數據,將數據文件加載即可,這樣可以確保數據的一致。同一組的slot文件,如果一臺機器加載不下,可以多臺機器加載,分布式服務做好控制即可。查詢時,像對key做hash,然后并發去查詢對應slot的服務即可。

輕量級KV系統設計

實際系統中,數據的key都是int64數據,value是json string,我們來設計hint和data文件格式。在不考慮校驗的情況下,我們可以用最簡單的文件格式來存儲。

離線寫入

hint格式,按照 key,value length,offset 依次寫入。

|  int64  key | int32 value length |  int64 value offset |  ... | int64  key | int32 value length |  int64 value offset |

data 格式,直接append 壓縮后的數據。

|  compressed value bytes | ... |  compressed value bytes |

簡單的java代碼實現:


FileOutputStream dataFileWriter = new FileOutputStream (outputFile);  
FileOutputStream indexFileWriter = new FileOutputStream(outPutIndex);  
long offset = 0;  
int count = 0;  
while (dataList.hasNext()) {  
    Document doc = dataList.next();  
    Long id = doc.getLong("_id");  
    byte[] value = compress(doc.toJson(),"utf-8");  
    byte[] length = intToByteLittle(value.length);  
  
    dataFileWriter.write(value);  
    offset +=  value.length;  
  
    indexFileWriter.write(longToBytesLittle(id));  
    indexFileWriter.write(length);  
    indexFileWriter.write(longToBytesLittle(offset));  
  
    count++;  
    if (count % 10000 == 0) {  
        log.info("already load {} items", count);  
        indexFileWriter.flush();  
        dataFileWriter.flush();  
    }  
}  
  
indexFileWriter.close();  
dataFileWriter.close();

在線讀取

讀取,需要先讀取hint索引文件,加載到內存。

// read index  
FileInputStream indexReader = new FileInputStream(indexFile);  
  
// id 8字節, offset 4字節  
byte[] entry = new byte[8+4+8];  
byte[] idBytes = new byte[8];  
byte[] lengthBytes = new byte[4];  
byte[] offsetBytes = new byte[8];  
Map<Long, Pair<Long, Integer>> id2Offset = new HashMap<>();  
// 這里直接加載到map里,可以優化  
while(indexReader.read(entry, 0, entry.length) > 0) {  
  
    System.arraycopy(entry,0, idBytes, 0, 8);  
    System.arraycopy(entry,8, lengthBytes, 0, 4);  
    System.arraycopy(entry,12, offsetBytes, 0, 8);  
    
    long id = EncodingUtils.bytesToLongLittle(idBytes);  
    int dataLength =  EncodingUtils.bytes2IntLittle(lengthBytes);  
    long offset =  EncodingUtils.bytesToLongLittle(offsetBytes);  
    id2Offset.put(id, Pair.of(offset, dataLength));  
}

從數據文件讀取數據也會比較簡單,先從hint數據獲取到key對應的offset和dataLength,然后讀取數據解壓即可。

RandomAccessFile dataFileReader = new RandomAccessFile(dataFile, "r");  
while(true) {  
    System.out.print("請輸入查詢key:");  
    String key =  System.console().readLine();  
    long id = Long.parseLong(key);  
    if (id2Offset.containsKey(id)) {  
        long offset = id2Offset.get(id).getFirst();  
        int dataSize =  id2Offset.get(id).getSecond();  
        dataFileReader.seek(offset);  
        byte[] data = new byte[dataSize];  
        dataFileReader.read(data, 0, data.length);  
        byte[] decodeData = uncompress(data);  
        System.out.println(new String(decodeData));  
    }  
}

上面僅僅是demo性質的代碼,實際過程中還要考慮數據的完整性檢驗,以及LRU緩存等。

總結

沒有最好的K-V系統,只有最適合應用業務實際場景的系統,做任何的方案選擇,要結合業務當前的實際情況綜合權衡,有所取有所舍。

總結

以上是生活随笔為你收集整理的从Bitcask存储模型谈超轻量级KV系统设计与实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 爱av导航 | 麻豆成人免费 | 日本丰满熟妇hd | 91精品专区 | 亚洲欧美另类视频 | 免费av大全 | 夫の上司に犯波多野结衣853 | 激情福利视频 | 欧美色久 | 夜夜爽夜夜操 | 精品成人一区二区 | 亚洲精视频 | 国产精品夜色一区二区三区 | 永久免费视频网站直接看 | 欧美一级高潮片 | 国产精品一区二区三区在线播放 | 男女一区| 国产校园春色 | 好吊妞在线观看 | 欧美国产日本 | 婷婷久久五月 | 国产jzjzjz丝袜老师水多 | 国产毛片久久久久久 | 亚洲大乳| 少妇aaaa| 亚洲AV无码久久精品国产一区 | 国产 欧美 日韩 一区 | 色婷婷aⅴ一区二区三区 | 成人毛片软件 | 91免费片| 制服诱惑一区 | 免费的理伦片在线播放 | 国产网址 | 五月婷婷,六月丁香 | 亚洲成a人片在线www | 伊人久久一区 | 亚洲国产无码精品 | 国产伦精品一区二区三区精品 | 国产免费黄色片 | 国产日韩二区 | 激情网五月 | 不卡中文字幕 | 国产无遮无挡120秒 欧美综合图片 | 亚洲欧美一区二区三区不卡 | 手机在线视频一区 | 亚洲精品乱码久久久久久蜜桃麻豆 | 亚洲精品综合在线 | 亚洲国产三区 | 91久久亚洲 | 哺乳期给上司喂奶hd | 精品视频一区二区在线 | 国产一级二级在线 | 成人国产视频在线观看 | 日韩aaa| 农村老熟妇乱子伦视频 | 波多野结衣免费在线视频 | 欧美视频自拍偷拍 | 波多野结衣视频一区二区 | 18视频在线观看娇喘 | 高h奶汁双性受1v1 | 成人黄色一级视频 | 亚洲一区二区三区在线免费观看 | 91视频网页| 色综合欧美| 日韩午夜一区 | av私库在线观看 | 91在线国产观看 | 性欧美1819性猛交 | 亚洲影视在线 | 色接久久 | 国产白拍| 黄色岛国片 | 亚洲视频中文字幕 | 国产第一页第二页 | 欧美一区二区三区不卡视频 | 国产精品伦一区二区三级视频 | 色www国产亚洲阿娇 自拍一区在线 | 久久久久久久久久艹 | 美色视频| 日韩精品一区二区三区不卡 | a视频免费看| 一边顶弄一边接吻 | 99re6在线视频 | 欧美色呦呦 | 日韩成人免费在线视频 | 国产精品午夜电影 | 91porny九色 | 婷婷精品 | 男同av在线观看一区二区三区 | 国产91视频播放 | 欧美一级黄色网 | 黄色免费网站在线 | 亲子乱aⅴ一区二区三区 | 欧美视频三区 | 日韩aaaaaa | 国产污视频在线播放 | 国产精品老牛影院99av | 9999久久久久 | 奇米影视四色在线 |