0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線(xiàn)課程
  • 觀(guān)看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

持久化數(shù)據(jù)到硬盤(pán)上并采用RocksDB作為存儲(chǔ)引擎

工程師鄧生 ? 來(lái)源:coding到燈火闌珊 ? 作者:李明 ? 2022-09-29 10:00 ? 次閱讀

在上一篇文章中,我們使用內(nèi)存做數(shù)據(jù)的存儲(chǔ)。在這一篇文章中,我們持久化數(shù)據(jù)到硬盤(pán)上,采用RocksDB作為存儲(chǔ)引擎。同時(shí)也增加了一個(gè)service層,將命令解析和存儲(chǔ)邏輯提取到這一層中。

RocksDB 先在Cargo.toml文件中加入rocksdb依賴(lài):

poYBAGM0_GqAZhS6AAAXGsoUAAs416.jpg

然后,在src/storage目錄下創(chuàng)建rocksdb_storage.rs文件。代碼如下:

 1#[derive(Debug)]
 2pubstructRocksDbStorage(DB);
 3
 4implRocksDbStorage{
 5pubfnnew(path:implAsRef)->Self{
 6Self(DB::open_default(path).unwrap())
 7}
 8}
 9
10implStorageforRocksDbStorage{
11fnget(&self,key:&str)->Result,Box>{
12letv=self.0.get(key)?.unwrap();
13Ok(Some(v.into()))
14}
15
16fnset(&self,key:&str,value:bytes::Bytes)->Result,Box>{
17self.0.put(key,value.clone()).unwrap();
18Ok(Some(value))
19}
20}
Service層 創(chuàng)建src/service目錄,然后創(chuàng)建mod.rs文件及cmd_service.rs文件。在mod.rs文件中加入如下代碼:
1pubmodcmd_service;
2
3pubtraitCmdService{
4//解析命令,返回Response
5fnexecute(self,store:&implStorage)->CmdResponse;
6}
在cmd_service.rs文件中為命令實(shí)現(xiàn)CmdService trait,代碼如下:
 1usecrate::{CmdResponse,CmdService,Get,Set};
 2
 3//為GET實(shí)現(xiàn)execute
 4implCmdServiceforGet{
 5fnexecute(self,store:&implcrate::Storage)->CmdResponse{
 6//從存儲(chǔ)中獲取數(shù)據(jù),返回CmdResponse
 7matchstore.get(&self.key){
 8Ok(Some(value))=>value.into(),
 9Ok(None)=>"Notfound".into(),
10Err(e)=>e.into(),
11}
12}
13}
14
15//為SET實(shí)現(xiàn)execute
16implCmdServiceforSet{
17//存儲(chǔ)數(shù)據(jù)
18fnexecute(self,store:&implcrate::Storage)->CmdResponse{
19matchstore.set(&self.key,self.value){
20Ok(Some(value))=>value.into(),
21Ok(None)=>"Setfail".into(),
22Err(e)=>e.into(),
23}
24}
25}
在src/pb/mod.rs中實(shí)現(xiàn)從Bytes、&str、Box轉(zhuǎn)換為CmdResponse:
 1implFromforCmdResponse{
 2fnfrom(v:Bytes)->Self{
 3Self{
 4status:200u32,
 5message:"success".to_string(),
 6value:v,
 7}
 8}
 9}
10
11implFrom<&str>forCmdResponse{
12fnfrom(s:&str)->Self{
13Self{
14status:400u32,
15message:s.to_string(),
16..Default::default()
17}
18}
19}
20
21implFrom>forCmdResponse{
22fnfrom(e:Box)->Self{
23Self{
24status:500u32,
25message:e.to_string(),
26..Default::default()
27}
28}
29}
然后在src/service/mod.rs中加入service代碼:
 1//設(shè)置默認(rèn)存儲(chǔ)為RocksDB
 2pubstructService{
 3store_svc:Arc>,
 4}
 5
 6//在多線(xiàn)程中進(jìn)行clone
 7pubstructStoreService{
 8store:Store,
 9}
10
11implService{
12pubfnnew(store:Store)->Self{
13Self{
14store_svc:Arc::new(StoreService{store}),
15}
16}
17
18//執(zhí)行命令
19pubasyncfnexecute(&self,cmd_req:CmdRequest)->CmdResponse{
20println!("===ExecuteCommandBefore===");
21letcmd_res=process_cmd(cmd_req,&self.store_svc.store).await;
22println!("===ExecuteCommandAfter===");
23cmd_res
24}
25}
26
27//實(shí)現(xiàn)Clonetrait
28implCloneforService{
29fnclone(&self)->Self{
30Self{
31store_svc:self.store_svc.clone(),
32}
33}
34}
35
36//處理請(qǐng)求命令,返回Response
37asyncfnprocess_cmd(cmd_req:CmdRequest,store:&implStorage)->CmdResponse{
38matchcmd_req.req_data{
39//處理GET命令
40Some(ReqData::Get(cmd_get))=>cmd_get.execute(store),
41//處理SET命令
42Some(ReqData::Set(cmd_set))=>cmd_set.execute(store),
43_=>"Invalidcommand".into(),
44}
45}

配置 我們修改配置,在conf/server.conf中加入RocksDB路徑
......[rocksdb_path]path = '/tmp/kvserver'
在src/config.rs中加入如下代碼:
 1//Server端配置
 2#[derive(Debug,Serialize,Deserialize)]
 3pubstructServerConfig{
 4......
 5pubrocksdb_path:RocksdbPath,
 6}
 7
 8......
 9
10//RocksDB存儲(chǔ)目錄
11#[derive(Debug,Serialize,Deserialize)]
12pubstructRocksdbPath{
13pubpath:String,
14}
修改kv_server 在kv_server.rs中使用service執(zhí)行命令,刪除process_cmd函數(shù):
 1#[tokio::main]
 2asyncfnmain()->Result<(),?Box>{
 3......
 4
 5//初始化Service及存儲(chǔ)
 6letservice=Service::new(RocksDbStorage::new(rocksdb_path));
 7
 8loop{
 9......
10letsvc=service.clone();
11
12tokio::spawn(asyncmove{
13//使用Frame的LengthDelimitedCodec進(jìn)行編解碼操作
14letmutstream=Framed::new(stream,LengthDelimitedCodec::new());
15whileletSome(Ok(mutbuf))=stream.next().await{
16......
17
18//執(zhí)行請(qǐng)求命令
19letcmd_res=svc.execute(cmd_req).await;
20
21......
22}
23info!("Client{:?}disconnected",addr);
24});
25}
26}

審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀(guān)點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 數(shù)據(jù)存儲(chǔ)

    關(guān)注

    5

    文章

    977

    瀏覽量

    50976
  • 編解碼
    +關(guān)注

    關(guān)注

    1

    文章

    140

    瀏覽量

    19635
  • Rust
    +關(guān)注

    關(guān)注

    1

    文章

    229

    瀏覽量

    6626

原文標(biāo)題:用Rust實(shí)現(xiàn)KV Server-4 持久化存儲(chǔ)及service層

文章出處:【微信號(hào):Rust語(yǔ)言中文社區(qū),微信公眾號(hào):Rust語(yǔ)言中文社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    SAS固態(tài)硬盤(pán)存儲(chǔ)技術(shù)

    SAS固態(tài)硬盤(pán)存儲(chǔ)技術(shù)是一種介于傳統(tǒng)硬盤(pán)和內(nèi)存之間的存儲(chǔ)技術(shù),在IOPS上,相比普通機(jī)械硬盤(pán)存儲(chǔ)速度快50
    發(fā)表于 06-18 05:00

    Docker持久數(shù)據(jù)存儲(chǔ)方案

    Docker持久存儲(chǔ)數(shù)據(jù)共享
    發(fā)表于 03-23 11:17

    硬盤(pán)是怎么來(lái)存儲(chǔ)數(shù)據(jù)的?

    存儲(chǔ)是模擬格式的音樂(lè),而硬盤(pán)上存儲(chǔ)的是數(shù)字格式的數(shù)據(jù)。寫(xiě)入時(shí),磁頭線(xiàn)圈上加電,在周?chē)a(chǎn)生磁場(chǎng),磁化其下的磁性材料;電流的方向不同,所以磁場(chǎng)的方向也不同,可以表示 0 和 1 的區(qū)別。
    發(fā)表于 07-07 08:03

    硬盤(pán)上數(shù)據(jù)是如何組織與管理的呢?

    硬盤(pán)的外部物理結(jié)構(gòu)是由哪些部分組成的?硬盤(pán)的內(nèi)部物理結(jié)構(gòu)是由哪些部分組成的?硬盤(pán)存儲(chǔ)的邏輯結(jié)構(gòu)是由哪些部分組成的?硬盤(pán)上數(shù)據(jù)是如何組織與管
    發(fā)表于 07-13 07:00

    OpenHarmony持久存儲(chǔ)UI狀態(tài):PersistentStorage

    最好是小于2kb的數(shù)據(jù),不要大量的數(shù)據(jù)持久,因?yàn)镻ersistentStorage寫(xiě)入磁盤(pán)的操作是同步的,大量的數(shù)據(jù)本地
    發(fā)表于 10-19 14:34

    HarmonyOS數(shù)據(jù)管理與應(yīng)用數(shù)據(jù)持久(一)

    為應(yīng)用提供Key-Value鍵值型的數(shù)據(jù)處理能力,支持應(yīng)用持久輕量級(jí)數(shù)據(jù),對(duì)其修改和查詢(xún)。當(dāng)用戶(hù)希望有一個(gè)全局唯一
    發(fā)表于 11-01 16:27

    Rocksdb原理簡(jiǎn)介

    Rocksdb作為當(dāng)下nosql中性能的代表被各個(gè)存儲(chǔ)組件(mysql、tikv、pmdk、bluestore)作為存儲(chǔ)
    的頭像 發(fā)表于 06-01 17:17 ?931次閱讀
    <b class='flag-5'>Rocksdb</b>原理簡(jiǎn)介

    如何開(kāi)啟RDB持久方式

    ? RDB快照(Redis DataBase) RDB是一種快照存儲(chǔ)持久方式,具體就是將Redis某一時(shí)刻的內(nèi)存數(shù)據(jù)保存到硬盤(pán)的文件當(dāng)中,
    的頭像 發(fā)表于 06-25 11:52 ?915次閱讀
    如何開(kāi)啟RDB<b class='flag-5'>持久</b><b class='flag-5'>化</b>方式

    Redis持久RDB方式介紹

    時(shí)Redis會(huì)自動(dòng)將內(nèi)存中的數(shù)據(jù)進(jìn)行快照持久硬盤(pán)。 觸發(fā)快照的時(shí)機(jī) 符合自定義配置的快照規(guī)
    的頭像 發(fā)表于 10-09 14:56 ?525次閱讀
    Redis<b class='flag-5'>持久</b><b class='flag-5'>化</b>RDB方式介紹

    redis兩種持久方式的區(qū)別

    Redis是一款高性能、開(kāi)源的鍵值存儲(chǔ)數(shù)據(jù)庫(kù),它支持多種數(shù)據(jù)結(jié)構(gòu),并且具有高效的內(nèi)存讀寫(xiě)以及持久功能。Redis的
    的頭像 發(fā)表于 12-04 11:12 ?539次閱讀

    redis持久機(jī)制和如何實(shí)現(xiàn)持久

    File)。 RDB是Redis默認(rèn)采用持久方式,它通過(guò)在指定時(shí)間間隔內(nèi)將內(nèi)存中的數(shù)據(jù)集快照寫(xiě)入磁盤(pán)的二進(jìn)制文件中,實(shí)現(xiàn)
    的頭像 發(fā)表于 12-05 10:02 ?479次閱讀

    redis持久機(jī)制優(yōu)缺點(diǎn)

    Redis是一個(gè)基于內(nèi)存的高性能鍵值存儲(chǔ)系統(tǒng),它提供了多種持久機(jī)制來(lái)保證數(shù)據(jù)的可靠性。本文將詳細(xì)介紹Redis的持久
    的頭像 發(fā)表于 12-05 10:03 ?749次閱讀

    redis里數(shù)據(jù)什么時(shí)候持久

    Redis是一種開(kāi)源的高性能、非關(guān)系型內(nèi)存數(shù)據(jù)庫(kù),它使用了鍵值對(duì)存儲(chǔ)數(shù)據(jù),并且支持多種數(shù)據(jù)結(jié)構(gòu)。 Redis提供了持久
    的頭像 發(fā)表于 12-05 10:05 ?472次閱讀

    EEPROM存儲(chǔ)器:實(shí)現(xiàn)數(shù)據(jù)持久存儲(chǔ)的關(guān)鍵組件

    在計(jì)算機(jī)系統(tǒng)中,存儲(chǔ)器是用于存儲(chǔ)數(shù)據(jù)和程序指令的關(guān)鍵部件。其中,EEPROM(電可擦除可編程只讀存儲(chǔ)器)作為一種非易失性
    的頭像 發(fā)表于 05-27 16:36 ?1581次閱讀

    硬盤(pán)擦除遇到硬盤(pán)上鎖怎么解決?完整指南告訴你

    本文深入探討硬盤(pán)上鎖原因及解決方案,提供PSID解鎖硬盤(pán)的詳細(xì)指南。了解硬盤(pán)加密、密碼遺失、Secure Erase中斷等導(dǎo)致硬盤(pán)鎖定的問(wèn)題,
    的頭像 發(fā)表于 12-17 16:32 ?520次閱讀
    <b class='flag-5'>硬盤(pán)</b>擦除遇到<b class='flag-5'>硬盤(pán)上</b>鎖怎么解決?完整指南告訴你