日韩性视频-久久久蜜桃-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系统设计与实现的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 国内精品久久久久久久久久久 | 日韩一三区| 999免费 | av超碰| 国产高潮久久 | 高清免费av| 不卡一二区| 欧美少妇激情 | 亚洲九九九 | 精品一区二区三区精华液 | 久久夜色精品国产噜噜亚洲av | 波多野结衣一区二区三区四区 | 亚洲孕交| 一区二区三区精 | 一级片视频免费观看 | 深夜在线免费视频 | 午夜精品免费视频 | 青草视频在线观看视频 | 久久国产精品无码一级毛片 | 日韩国产免费 | 情侣黄网站免费看 | 国产情侣一区二区 | 国产亚洲欧美一区二区三区 | 经典一区二区三区 | 精品国产黄色 | 亚洲伦理视频 | 欧美欧美欧美 | 尤物网站在线播放 | 操综合 | 日日摸天天爽天天爽视频 | 国产精品福利在线 | 在线观看欧美一区二区 | 久久激情影院 | 色婷婷天堂 | 免费精品在线 | 国产91页 | 伊人狼人久久 | 操xxxx| 国产视频欧美视频 | 亚洲综人网 | 91美女在线 | 可以看毛片的网站 | 色爽爽爽| 九九综合九九综合 | 成人av动漫在线观看 | 国产日韩欧美视频 | 国内一区二区三区 | 欧美老熟妇乱xxxxx | 奴性女会所调教 | 亚洲成人av综合 | 麻豆蜜桃在线观看 | 久久久久麻豆 | 一区二区手机在线 | 国产精品欧美亚洲 | 欧美高清成人 | 无码人妻aⅴ一区二区三区 国产高清一区二区三区四区 | 少妇高潮毛片色欲ava片 | 国产精品美女久久久免费 | 在线播放日韩av | 免费一级黄色片 | 亚洲精品久久久久久久久久久 | 国产精品久久久久久在线观看 | 欧美三级视频网站 | 潮喷失禁大喷水aⅴ无码 | 国产精品毛片一区二区三区 | 亚洲一区二区三区精品视频 | 姐姐你真棒插曲快来救救我电影 | 亚洲黄色大片 | 亚洲精品久久 | 国产极品视频 | 久久美| 国产精品人人妻人人爽 | 久久午夜激情 | 97色伦图片| 偷拍第一页 | 福利一区二区在线 | 久久精品噜噜噜成人88aⅴ | 日本精品免费一区二区三区 | 日本五十路女优 | 在线观看免费国产 | 韩国美女啪啪 | 日韩欧美久久久 | 精品国产户外野外 | 十八禁一区二区三区 | 亚洲精品xxxx | 美女啪啪国产 | 国产又大又粗又长 | 午夜精品免费观看 | 国产20页| 国产无码精品一区二区 | 国产成人观看 | 性折磨bdsm欧美激情另类 | 国产成人午夜 | 一区视频 | www性欧美 | 特级做a爰片毛片免费69 | 曰批视频在线观看 | 亚洲另类在线观看 | 欧美黄色免费在线观看 |