<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          超級輕量級: KV存儲引擎實(shí)現(xiàn)

          共 4568字,需瀏覽 10分鐘

           ·

          2022-03-10 19:44

          Hi (????)?”,各位Gopher本人最近又用Go造了一個輪子,一個超級輕量級KV存儲引擎,歡迎????各位Gopher進(jìn)行評測。

          主頁介紹:https://bottle.ibyte.me (PC效果更佳??)

          項(xiàng)目地址:https://github.com/auula/bottle

          特 性

          • 嵌入的存儲引擎
          • 數(shù)據(jù)可以加密存儲
          • 可以自定義實(shí)現(xiàn)存儲加密器
          • 即使數(shù)據(jù)文件被拷貝,也保證存儲數(shù)據(jù)的安全
          • 未來索引數(shù)據(jù)結(jié)構(gòu)也可以支持自定義實(shí)現(xiàn)

          簡 介

          首先要說明的是Bottle是一款KV嵌入式存儲引擎,并非是一款KV數(shù)據(jù)庫,我知道很多人看到了KV認(rèn)為是數(shù)據(jù)庫,當(dāng)然不是了,很多人會把這些搞混淆掉,KV存儲可以用來存儲很多東西,而并非是數(shù)據(jù)庫這一領(lǐng)域。可以這么理解數(shù)據(jù)庫是一臺汽車,那么Bottle是一臺車的發(fā)動機(jī)??梢院唵卫斫?code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">Bottle是一個對操作系統(tǒng)文件系統(tǒng)的KV抽象化封裝,可以基于Bottle做為存儲層,在Bottle層之上封裝一些數(shù)據(jù)結(jié)構(gòu)和對外服務(wù)的協(xié)議就可以實(shí)現(xiàn)一個數(shù)據(jù)庫。

          層次架構(gòu)圖

          本項(xiàng)目功能實(shí)現(xiàn)完全基于?bitcask?論文所實(shí)現(xiàn),另外本項(xiàng)目所用到一些知識和卡內(nèi)基梅隆大學(xué)CMU 15-445: Database Systems課程內(nèi)容很接近,這門課由數(shù)據(jù)庫領(lǐng)域的大牛Andy Pavlo講授,有感興趣的朋友可以去看看這套課,如果覺得不錯你可以給我按一顆小星?謝謝。

          安裝Bottle

          你只需要在你的項(xiàng)目中安裝Bottle模塊即可使用:

          go?get?-u?github.com/auula/bottle

          基本API

          如何操作一個Bottle實(shí)例代碼:

          package?main

          import?(
          ????"fmt"
          ????"github.com/auula/bottle"
          )

          func?init()?{
          ????//?通過默認(rèn)配置打開一個存儲實(shí)例
          ????err?:=?bottle.Open(bottle.DefaultOption)
          ????//?并且處理一下可能發(fā)生的錯誤
          ????if?err?!=?nil?{
          ????????panic(err)
          ????}
          }

          //?Userinfo?測試數(shù)據(jù)結(jié)構(gòu)
          type?Userinfo?struct?{
          ????Name??string
          ????Age???uint8
          ????Skill?[]string
          }

          func?main()?{

          ????//?PUT?Data
          ????bottle.Put([]byte("foo"),?[]byte("66.6"))

          ????//?如果轉(zhuǎn)成string那么就是字符串
          ????fmt.Println(bottle.Get([]byte("foo")).String())

          ????//?如果不存在默認(rèn)值就是0
          ????fmt.Println(bottle.Get([]byte("foo")).Int())

          ????//?如果不成功就是false
          ????fmt.Println(bottle.Get([]byte("foo")).Bool())

          ????//?如果不成功就是0.0
          ????fmt.Println(bottle.Get([]byte("foo")).Float())

          ????user?:=?Userinfo{
          ????????Name:??"Leon?Ding",
          ????????Age:???22,
          ????????Skill:?[]string{"Java",?"Go",?"Rust"},
          ????}

          ????var?u?Userinfo

          ????//?通過Bson保存數(shù)據(jù)對象,并且設(shè)置超時時間為5秒,TTL超時可以不設(shè)置看需求
          ????bottle.Put([]byte("user"),?bottle.Bson(&user),?bottle.TTL(5))

          ????//?通過Unwrap解析出結(jié)構(gòu)體
          ????bottle.Get([]byte("user")).Unwrap(&u)

          ????//?打印取值
          ????fmt.Println(u)

          ????//?刪除一個key
          ????bottle.Remove([]byte("foo"))

          ????//?關(guān)閉處理一下可能發(fā)生的錯誤
          ????if?err?:=?bottle.Close();?err?!=?nil?{
          ????????fmt.Println(err)
          ????}
          }

          加密器

          數(shù)據(jù)加密器是針對數(shù)據(jù)的value記錄的,也就是針對字段級別的區(qū)塊加密,并非是把整個文件加密一遍,那樣設(shè)計會帶來性能消耗,所以采用區(qū)塊數(shù)據(jù)段方式加密的方式。

          下面例子是通過bottle.SetEncryptor(Encryptor,[]byte)函數(shù)去設(shè)置數(shù)據(jù)加密器并且配置16位的數(shù)據(jù)加密秘鑰。

          func?init()?{
          ????bottle.SetEncryptor(bottle.AES(),?[]byte("1234567890123456"))
          }

          你也可以自定義去實(shí)現(xiàn)數(shù)據(jù)加密器的接口:

          //?SourceData?for?encryption?and?decryption
          type?SourceData?struct?{
          ????Data???[]byte
          ????Secret?[]byte
          }

          //?Encryptor?used?for?data?encryption?and?decryption?operation
          type?Encryptor?interface?{
          ????Encode(sd?*SourceData)?error
          ????Decode(sd?*SourceData)?error
          }

          下面代碼就是內(nèi)置AES加密器的實(shí)現(xiàn)代碼,實(shí)現(xiàn)bottle.Encryptor接口即可,數(shù)據(jù)源為bottle.SourceData?結(jié)構(gòu)體字段:

          //?AESEncryptor?Implement?the?Encryptor?interface
          type?AESEncryptor?struct{}

          //?Encode?source?data?encode
          func?(AESEncryptor)?Encode(sd?*SourceData)?error?{
          ????sd.Data?=?aesEncrypt(sd.Data,?sd.Secret)
          ????return?nil
          }

          //?Decode?source?data?decode
          func?(AESEncryptor)?Decode(sd?*SourceData)?error?{
          ????sd.Data?=?aesDecrypt(sd.Data,?sd.Secret)
          ????return?nil
          }

          具體的加密器實(shí)現(xiàn)代碼可以查看encrypted.go

          散列函數(shù)

          如果你需要自定義實(shí)現(xiàn)散列函數(shù),實(shí)現(xiàn)bottle.Hashed?接口即可:

          type?Hashed?interface?{
          ????Sum64([]byte)?uint64
          }

          然后通過內(nèi)置的bottle.SetHashFunc(hash Hashed)?設(shè)置即可完成你的散列函數(shù)配置。

          索引大小

          索引預(yù)設(shè)置的大小很大程度上會影響你的程序存取和讀取數(shù)據(jù)的速度,如果在初始化的時候能夠預(yù)計出程序運(yùn)行時需要的索引大小,并且在初始化的時候配置好,可以減小程序在運(yùn)行過程中帶來的運(yùn)行數(shù)據(jù)遷移和擴(kuò)容帶來的性能問題。

          func?init()?{
          ????//?設(shè)置索引大小?
          ????bottle.SetIndexSize(1000)
          }

          配置信息

          你也可以不使用默認(rèn)配置,你可以使用內(nèi)置的bottle.Option?的結(jié)構(gòu)體初始化你存儲引擎,配置實(shí)例如下:

          func?init()?{
          ????????//?自定義配置信息
          ????????option?:=?bottle.Option{
          ????????//?工作目錄
          ????????Directory:???????"./data",
          ????????//?算法開啟加密
          ????????Enable:??????????true,
          ????????//?自定義秘鑰,可以使用內(nèi)置的秘鑰
          ????????Secret:??????????bottle.Secret,
          ????????//?自定義數(shù)據(jù)大小,存儲單位是kb
          ????????DataFileMaxSize:?1048576,
          ????}
          ????//?通過自定義配置信息
          ????bottle.Open(option)
          }

          當(dāng)然也可以使用內(nèi)置的bottle.Load(path string)?函數(shù)加載配置文件啟動Bottle,配置文件格式為yaml,可配置項(xiàng)如下:

          #?Bottle?config?options
          Enable:?TRUE
          Secret:?"1234567890123456"
          Directory:?"./testdata"
          DataFileMaxSize:?536870912

          需要注意的是內(nèi)置的加密器實(shí)現(xiàn)的秘鑰必須是16位,如果你是自定義實(shí)現(xiàn)的加密器可通過bottle.SetEncryptor(Encryptor,[]byte)設(shè)置你自定義的加密器,那這個秘鑰位數(shù)將不受限制。

          數(shù)據(jù)目錄

          由于bottle設(shè)計就是基于但進(jìn)程的程序,所以每個存儲實(shí)例對應(yīng)是一個數(shù)據(jù)目錄,data為日志合并結(jié)構(gòu)數(shù)據(jù)目錄,index為索引數(shù)據(jù)版本。

          日志合并結(jié)構(gòu)數(shù)據(jù)目前版本是每次數(shù)據(jù)啟動時候進(jìn)行合并,默認(rèn)是data數(shù)據(jù)文件夾下的所有數(shù)據(jù)文件占用總和超過1GB就會觸發(fā)一次合并,合并之后沒有用的數(shù)據(jù)被丟棄。

          當(dāng)然如果未達(dá)到臟數(shù)據(jù)合并要求,數(shù)據(jù)文件會以啟動時候配置的大小進(jìn)行歸檔,每個數(shù)據(jù)有版本號,并且被設(shè)置為只讀掛載,進(jìn)程工作目錄結(jié)構(gòu)如下:

          ./testdata
          ├──?data
          │???└──?1.data
          └──?index
          ????├──?1646378326.index
          ????└──?1646378328.index

          2?directories,?3?files

          當(dāng)存儲引擎開始工作的時候,這個目錄下的所以文件夾和文件只能被這個進(jìn)程操作,保證數(shù)據(jù)安全。

          后續(xù)維護(hù)

          • Bottle目前不支持多數(shù)據(jù)存儲分區(qū),后續(xù)版本會引入一個Bucket概念,未來可以把指定的數(shù)據(jù)存儲到指定的分區(qū)中,來降低并發(fā)的時候索引鎖的顆粒度。
          • 后續(xù)將引入零拷貝技術(shù),當(dāng)前文件操作很大程度上依賴于操作系統(tǒng),當(dāng)前文件必須sync才能保證數(shù)據(jù)一致性。
          • 臟數(shù)據(jù)合并可以在運(yùn)行中進(jìn)行合并整理,基于信號量的方式通知垃圾回收工作線程。

          其他信息

          如果你發(fā)現(xiàn)了bug歡迎提issue或者發(fā)起pull request,我收到了消息會盡快回復(fù)你,另外歡迎各位Gopher提出自己意見,或者貢獻(xiàn)自己的代碼也是可以的,另外我們也非常歡迎大家進(jìn)行存儲相關(guān)技術(shù)交流,不錯的話別忘去Github點(diǎn)一個?Thanks?(?ω?)?。

          更詳細(xì)的問題可以查看:https://github.com/auula/bottle


          想要了解更多與Go語言相關(guān)的內(nèi)容,歡迎入群和我們進(jìn)行交流~



          瀏覽 29
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  中文精品无码视频 | 国产最新网址 | 男女拍拍拍 | 俺去也俺就去www色情网最新更新内容 | 东京热久久综合 |