作者:ReganYue

來(lái)源:恒生LIGHT云社區(qū)

一、什么是BoltDB

這是一款純粹使用Go語(yǔ)言編寫(xiě)的key/value數(shù)據(jù)庫(kù),據(jù)說(shuō)它是參考了開(kāi)源的內(nèi)存映射數(shù)據(jù)庫(kù)LMDB。值得注意的是,這款數(shù)據(jù)庫(kù)不支持網(wǎng)絡(luò)連接,也沒(méi)有復(fù)雜的SQL語(yǔ)句查詢(xún)支持。但是它在Go的應(yīng)用中能夠比較方便的來(lái)達(dá)到數(shù)據(jù)持久化。

二、使用場(chǎng)景

  1. Go語(yǔ)言編寫(xiě)的程序,這個(gè)程序需要內(nèi)嵌數(shù)據(jù)庫(kù)。
  2. 不需要復(fù)雜的SQL語(yǔ)句查詢(xún)。
  3. 這款數(shù)據(jù)庫(kù)更擅長(zhǎng)讀的操作,所以在讀多寫(xiě)少的場(chǎng)景下,它效果比較好。

三、安裝及使用方法

安裝方法很簡(jiǎn)單,就是在命令行執(zhí)行:

go get github.com/boltdb/bolt/...

那么我們?nèi)绾未蜷_(kāi)數(shù)據(jù)庫(kù)呢?我們來(lái)看一看下面這段代碼。

package mainimport (    "log"    "github.com/boltdb/bolt")func main() {    // Open the my.db data file in your current directory.    // It will be created if it doesnt exist.    db, err := bolt.Open("my.db", 0600, nil)    if err != nil {        log.Fatal(err)    }    defer db.Close()    ...}

這個(gè) bolt.Open()是在給定的路徑上打開(kāi)數(shù)據(jù)庫(kù)。如果要打開(kāi)的數(shù)據(jù)庫(kù)文件不存在,則將自動(dòng)創(chuàng)建該文件。**
**第二個(gè)參數(shù)是文件模式。第三個(gè)參數(shù)傳入nil值就讓Bolt使用默認(rèn)選項(xiàng)打開(kāi)數(shù)據(jù)庫(kù)。

Bolt 多個(gè)進(jìn)程無(wú)法同時(shí)打開(kāi)同一個(gè)數(shù)據(jù)庫(kù)。打開(kāi)一個(gè)已經(jīng)打開(kāi)的 Bolt 數(shù)據(jù)庫(kù)會(huì)導(dǎo)致它掛起,直到另一個(gè)進(jìn)程關(guān)閉它。為了防止無(wú)限期等待,我們需要給 Open()函數(shù)一個(gè)超時(shí)參數(shù):

db, err := bolt.Open("my.db", 0600, &bolt.Options{Timeout: 1 * time.Second})

事務(wù)

Bolt一次只支持一個(gè)讀寫(xiě)事務(wù),但是一次可以支持多個(gè)只讀事務(wù)。

用于讀寫(xiě)的事務(wù)API是Update,二用于讀的事務(wù)API是View。

err := db.Update(func(tx *bolt.Tx) error {    ...    return nil})
err := db.View(func(tx *bolt.Tx) error {    ...    return nil})

注意:只讀事務(wù)和讀寫(xiě)事務(wù)通常不應(yīng)同時(shí)在同一個(gè) goroutine 中打開(kāi)。這可能會(huì)導(dǎo)致死鎖,因?yàn)樽x寫(xiě)事務(wù)需要定期重新映射數(shù)據(jù)文件,但在只讀事務(wù)打開(kāi)時(shí)無(wú)法這樣做。

還有一種****Batch事務(wù)**可以減小并發(fā)寫(xiě)操作的開(kāi)銷(xiāo)。Batch 僅在有多個(gè) goroutine 調(diào)用它時(shí)才有用。**

err := db.Batch(func(tx *bolt.Tx) error {    ...    return nil})

讀寫(xiě)操作

db.Update(func(tx *bolt.Tx) error {    b := tx.Bucket([]byte("MyBucket"))    err := b.Put([]byte("answer"), []byte("42"))    return err})

這是往數(shù)據(jù)庫(kù)中寫(xiě)入鍵為answer值為42的數(shù)據(jù)。

db.View(func(tx *bolt.Tx) error {    b := tx.Bucket([]byte("MyBucket"))    v := b.Get([]byte("answer"))    fmt.Printf("The answer is: %s/n", v)    return nil})

這是讀取鍵為answer的數(shù)據(jù)。

是不是發(fā)現(xiàn)有個(gè)tx.Bucket()不知道是干什么的呢?

Bolt有個(gè)很有意思的地方就是這個(gè)Bucket,這個(gè)是這個(gè)數(shù)據(jù)庫(kù)組織數(shù)據(jù)的基本方式,比如有一個(gè)Bucket叫公司,這個(gè)Bucket里面還建一個(gè)Bucket叫部門(mén),里面建一個(gè)key:ReganYue,這就說(shuō)明ReganYue是這個(gè)部門(mén)里面的人,但是同時(shí)也是這個(gè)公司里面的人,這個(gè)key屬于部門(mén)這個(gè)Bucket,也屬于公司這個(gè)Bucket。