介紹BoltDB:Golang高性能持久化解決方案

介紹BoltDB:Golang高性能持久化解決方案

1. 介紹Bolt

BoltDB是純Go語言實現的持久化解決方案,保存數據至內存映射文件。稱之爲持久化解決方案不是數據庫,因爲數據庫這個詞有很多額外功能是bolt所不具備的。正是因爲缺乏這些功能使得bolt如此優雅、好用。

Bolt就是一個Go包。無需在系統中安裝,開始編碼前也無需配置,什麼都不需要,僅需要go get github.com/boltdb/bolt,然後import “github.com/boltdb/bolt”

要完全使用bolt的存儲功能,只需要一個文件名。無論從開發者或用戶視角都感覺不可思議。不知你的感想如何,在我的工作經歷中花過很多時間搭建數據庫環境,調試配置問題,用戶和權限以及其他各種問題,如關係型數據庫PostgreSql、Oracle和NoSQL。這些bolt都不需要,沒有用戶、無需安裝,僅一個文件名。這對應用程序的用戶來說也是一種恩惠,因爲他們也不必爲那些麻煩問題而瞎折騰。

Bolt不是關係型數據庫。甚至不存儲文檔,雖然你可以按照這種方式使用它。其僅僅存儲鍵值對…但是如果你不知道這是什麼意思或者不知道你如何使用它進行存儲,也不用擔心。它超級簡單,而且非常靈活,讓我們來看看。

2. 示例

bolt存儲是分組爲桶,桶是一組鍵值對集合的名稱,就像Go中的map。桶的名稱、鍵以及值都是[]byte類型。桶可以包括其他桶,也可以通過[]byte類型名稱作爲key。

…就是這樣。不,真的,就這樣。Bolt基本上是一組嵌套映射。這種簡單性使得它易於使用。不需要設置表、模式、複雜的查詢語言。讓我們看看一個bolt入門示例:

package main

import (
	"fmt"
	"github.com/boltdb/bolt"
	"log"
)

var world = []byte("greeting")

func main() {
	db, err := bolt.Open("d:/bolt.db", 0644, nil)
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	key := []byte("hello")
	value := []byte("Hello World!")

	// store some data
	err = db.Update(func(tx *bolt.Tx) error {
		bucket, err := tx.CreateBucketIfNotExists(world)
		if err != nil {
			return err
		}

		err = bucket.Put(key, value)
		if err != nil {
			return err
		}
		return nil
	})

	if err != nil {
		log.Fatal(err)
	}

	// retrieve the data
	err = db.View(func(tx *bolt.Tx) error {
		bucket := tx.Bucket(world)
		if bucket == nil {
			return fmt.Errorf("Bucket %s not found!", world)
		}

		val := bucket.Get(key)
		fmt.Println(string(val))

		return nil
	})

	if err != nil {
		log.Fatal(err)
	}
}

輸出:Hello World!

我想你正在思索————這代碼似乎有點長。但請記住,我完全處理了所有錯誤,至少是半正確的方式,我們正在做的所有這些:

  1. 創建數據庫
  2. 創建結構(greeting分組)
  3. 存儲數據到結構中
  4. 從結構中獲取數據

不算太壞,加上空行也不過54行代碼。下面詳細解釋下上面示例具體實現內容。

3. 示例分析

首先bolt.Open連接數據庫,如果需要創建文件或打開已存在的文件。
所有bolt讀寫操作都必須在事務內進行。在只讀事務中同時可以有很多讀操作,但寫操作一次只能有一個(當寫入器寫入時,讀取器維護數據庫的一致視圖)。

剛開始調用db.Update,帶有一個函數作爲參數,函數自身的參數爲bolt.Tx ————bolt的事務對象。然後創建桶(bolt所有數據都用桶組織),接着增加鍵值對。寫事務完成後開始讀操作————使用DB.View事務獲取剛寫入的數據。

bolt事務機制的強大之處在於它超級簡單——函數作用域就是事務的範圍。如果函數傳入Update並返回nil,事務中所有更新操作是原子的存入庫中。如果函數返回錯誤則事務回滾。這使得bolt事務對Go開發者來說非常簡單。只要像平時一樣返回一個錯誤,就可以提前退出函數,bolt也做了正確的事情。無需擔心手動回滾更新或其他事情,只需返回一個錯誤。

你可能需要另一個基本操作是遍歷桶中的鍵/值對,在這種情況下,只需調用Bucket.Cursor(),它返回一個遊標值,它有Next()、Prev()等函數,它們返回鍵/值對,並像您預期的那樣工作。

bolt API還有很多內容,但剩下的大部分內容都是關於數據庫統計和一些更高級使用場景內容……但要開始在bolt數據庫中存儲數據,上述內容就是你真正需要知道的。

4. 總結

對於更復雜的應用程序,僅在數據庫中存儲字符串可能不夠,但這沒關係,Go的編碼相關包可以幫忙。你可以很容易地使用encoding/json或encoding/gob將結構序列化到數據庫中,以唯一的名稱或id作爲鍵。再者bolt的好處是較低的使用門檻,不需要找出整個數據庫模式或安裝任何東西,就可以以高性能、可管理的方式將數據存儲至磁盤。

bolt的主要缺點是沒有查詢。你不能要求:給我所有以bar開頭foo對象。您可以在數據庫中創建自己的索引,並手動保持其更新。這很簡單,只需爲特定查詢將IDs切片(slice)序列化到“indices”桶中即可。顯然這是開始開發自己關係數據庫的領域,但是如果你不打算做得太過火,那麼所有這些代碼就夠了。那些外部DSL中的查詢只是爲內存中數據存儲編寫的代碼。

Bolt並非適用於所有應用。你必須瞭解應用程序的需求,以及bolt的鍵/值樣式是否足以滿足這些需求。如果是這樣,我想你會非常樂意使用簡單的數據存儲系統,而無需太多的腦力開銷。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章