golang高性能键值存储插件库badger的使用

Golang高性能键值存储插件库Badger的使用

BadgerDB是一个用纯Go编写的高性能键值存储数据库,具有嵌入式、持久化和快速的特点。它是分布式图数据库Dgraph的底层数据库,旨在成为RocksDB等非Go键值存储的高性能替代品。

BadgerDB简介

BadgerDB的设计基于论文《WiscKey: Separating Keys from Values in SSD-conscious Storage》,主要设计目标包括:

  • 用纯Go编写键值数据库
  • 利用最新研究成果构建适用于TB级数据集的最快KV数据库
  • 针对SSD进行优化

安装Badger

要开始使用Badger,需要安装Go 1.21或更高版本。Badger v3及以上版本需要使用Go模块。在项目中运行以下命令:

go get github.com/dgraph-io/badger/v4

基本使用示例

下面是一个完整的BadgerDB使用示例:

package main

import (
	"fmt"
	"log"

	"github.com/dgraph-io/badger/v4"
)

func main() {
	// 打开数据库
	db, err := badger.Open(badger.DefaultOptions("").WithInMemory(true))
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// 写入数据
	err = db.Update(func(txn *badger.Txn) error {
		err := txn.Set([]byte("answer"), []byte("42"))
		return err
	})
	if err != nil {
		log.Fatal(err)
	}

	// 读取数据
	err = db.View(func(txn *badger.Txn) error {
		item, err := txn.Get([]byte("answer"))
		if err != nil {
			return err
		}

		val, err := item.ValueCopy(nil)
		if err != nil {
			return err
		}

		fmt.Printf("The answer is: %s\n", val)
		return nil
	})
	if err != nil {
		log.Fatal(err)
	}

	// 迭代所有键值对
	err = db.View(func(txn *badger.Txn) error {
		opts := badger.DefaultIteratorOptions
		opts.PrefetchSize = 10
		it := txn.NewIterator(opts)
		defer it.Close()

		for it.Rewind(); it.Valid(); it.Next() {
			item := it.Item()
			k := item.Key()
			v, err := item.ValueCopy(nil)
			if err != nil {
				return err
			}
			fmt.Printf("key=%s, value=%s\n", k, v)
		}
		return nil
	})
	if err != nil {
		log.Fatal(err)
	}
}

事务处理示例

Badger支持ACID事务,以下是一个事务处理的示例:

package main

import (
	"fmt"
	"log"

	"github.com/dgraph-io/badger/v4"
)

func main() {
	// 打开数据库
	db, err := badger.Open(badger.DefaultOptions("").WithInMemory(true))
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// 开始一个读写事务
	txn := db.NewTransaction(true)
	defer txn.Discard()

	// 在事务中执行多个操作
	err = txn.Set([]byte("name"), []byte("Alice"))
	if err != nil {
		log.Fatal(err)
	}

	err = txn.Set([]byte("age"), []byte("30"))
	if err != nil {
		log.Fatal(err)
	}

	// 提交事务
	if err := txn.Commit(); err != nil {
		log.Fatal(err)
	}

	// 读取验证
	err = db.View(func(txn *badger.Txn) error {
		item, err := txn.Get([]byte("name"))
		if err != nil {
			return err
		}
		val, err := item.ValueCopy(nil)
		if err != nil {
			return err
		}
		fmt.Printf("Name: %s\n", val)

		item, err = txn.Get([]byte("age"))
		if err != nil {
			return err
		}
		val, err = item.ValueCopy(nil)
		if err != nil {
			return err
		}
		fmt.Printf("Age: %s\n", val)
		return nil
	})
	if err != nil {
		log.Fatal(err)
	}
}

TTL(生存时间)示例

Badger支持为键设置TTL(生存时间),过期后键会自动删除:

package main

import (
	"fmt"
	"log"
	"time"

	"github.com/dgraph-io/badger/v4"
)

func main() {
	// 打开数据库
	db, err := badger.Open(badger.DefaultOptions("").WithInMemory(true))
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// 设置一个5秒后过期的键
	err = db.Update(func(txn *badger.Txn) error {
		e := badger.NewEntry([]byte("temp"), []byte("expires soon")).WithTTL(5 * time.Second)
		return txn.SetEntry(e)
	})
	if err != nil {
		log.Fatal(err)
	}

	// 立即读取
	err = db.View(func(txn *badger.Txn) error {
		item, err := txn.Get([]byte("temp"))
		if err != nil {
			return err
		}
		val, err := item.ValueCopy(nil)
		if err != nil {
			return err
		}
		fmt.Printf("Before expiration: %s\n", val)
		return nil
	})
	if err != nil {
		log.Fatal(err)
	}

	// 等待6秒后键应该已过期
	time.Sleep(6 * time.Second)

	// 再次尝试读取
	err = db.View(func(txn *badger.Txn) error {
		_, err := txn.Get([]byte("temp"))
		if err == badger.ErrKeyNotFound {
			fmt.Println("Key has expired as expected")
			return nil
		}
		return err
	})
	if err != nil {
		log.Fatal(err)
	}
}

性能对比

Badger与其他流行键值存储的性能对比:

特性 Badger RocksDB BoltDB
设计 带值日志的LSM树 仅LSM树 B+树
高读取吞吐量
高写入吞吐量
为SSD设计 不专门
可嵌入
排序KV访问
纯Go(无Cgo)
事务 是,ACID,支持SSI并发 是(非ACID) 是,ACID
快照
TTL支持
三维访问(键-值-版本)

BadgerDB是一个成熟稳定的键值存储解决方案,已被许多知名项目采用,包括Dgraph、Jaeger Tracing、IPFS等。它特别适合需要高性能、低延迟和SSD优化的应用场景。


更多关于golang高性能键值存储插件库badger的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang高性能键值存储插件库badger的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


BadgerDB 使用指南

BadgerDB 是一个纯 Go 语言编写的高性能键值存储数据库,特别适合需要低延迟读写和高吞吐量的应用场景。下面我将详细介绍 BadgerDB 的使用方法。

1. 安装 BadgerDB

首先安装 BadgerDB 包:

go get github.com/dgraph-io/badger/v3

2. 基本使用

2.1 打开数据库

package main

import (
	"log"

	"github.com/dgraph-io/badger/v3"
)

func main() {
	// 打开数据库
	db, err := badger.Open(badger.DefaultOptions("/tmp/badger"))
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()
	
	// 数据库操作...
}

2.2 写入数据

err = db.Update(func(txn *badger.Txn) error {
    err := txn.Set([]byte("answer"), []byte("42"))
    return err
})
if err != nil {
    log.Fatal(err)
}

2.3 读取数据

err = db.View(func(txn *badger.Txn) error {
    item, err := txn.Get([]byte("answer"))
    if err != nil {
        return err
    }
    
    val, err := item.ValueCopy(nil)
    if err != nil {
        return err
    }
    
    log.Printf("The answer is: %s\n", val)
    return nil
})
if err != nil {
    log.Fatal(err)
}

3. 高级特性

3.1 迭代器

err = db.View(func(txn *badger.Txn) error {
    opts := badger.DefaultIteratorOptions
    opts.PrefetchSize = 10
    it := txn.NewIterator(opts)
    defer it.Close()
    
    for it.Rewind(); it.Valid(); it.Next() {
        item := it.Item()
        k := item.Key()
        v, err := item.ValueCopy(nil)
        if err != nil {
            return err
        }
        log.Printf("key=%s, value=%s\n", k, v)
    }
    return nil
})

3.2 前缀扫描

err = db.View(func(txn *badger.Txn) error {
    it := txn.NewIterator(badger.DefaultIteratorOptions)
    defer it.Close()
    
    prefix := []byte("ans")
    for it.Seek(prefix); it.ValidForPrefix(prefix); it.Next() {
        item := it.Item()
        k := item.Key()
        v, err := item.ValueCopy(nil)
        if err != nil {
            return err
        }
        log.Printf("key=%s, value=%s\n", k, v)
    }
    return nil
})

3.3 设置TTL(生存时间)

err = db.Update(func(txn *badger.Txn) error {
    // 设置5秒后过期
    e := badger.NewEntry([]byte("answer"), []byte("42")).WithTTL(5 * time.Second)
    err := txn.SetEntry(e)
    return err
})

4. 性能优化配置

opts := badger.DefaultOptions("/tmp/badger")
opts.ValueLogFileSize = 1024 * 1024 * 100 // 100MB
opts.ValueLogMaxEntries = 100000
opts.MaxTableSize = 64 << 20 // 64MB
opts.NumMemtables = 5
opts.NumLevelZeroTables = 5
opts.NumLevelZeroTablesStall = 10
opts.SyncWrites = false // 关闭同步写入可提高性能

db, err := badger.Open(opts)

5. 批量写入

wb := db.NewWriteBatch()
defer wb.Cancel()

for i := 0; i < 1000; i++ {
    key := []byte(fmt.Sprintf("key-%d", i))
    value := []byte(fmt.Sprintf("value-%d", i))
    if err := wb.Set(key, value, 0); err != nil {
        log.Fatal(err)
    }
}

if err := wb.Flush(); err != nil {
    log.Fatal(err)
}

6. 备份与恢复

6.1 备份

backupFile, err := os.Create("/tmp/badger-backup")
if err != nil {
    log.Fatal(err)
}
defer backupFile.Close()

_, err = db.Backup(backupFile, 0)
if err != nil {
    log.Fatal(err)
}

6.2 恢复

backupFile, err := os.Open("/tmp/badger-backup")
if err != nil {
    log.Fatal(err)
}
defer backupFile.Close()

err = db.Load(backupFile, 16)
if err != nil {
    log.Fatal(err)
}

7. 关闭数据库

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

总结

BadgerDB 是一个性能优异的键值存储数据库,特别适合 Go 语言项目。它提供了丰富的 API 和配置选项,可以满足不同场景的需求。使用时需要注意:

  1. 读写操作需要在事务中进行
  2. 合理配置参数以获得最佳性能
  3. 及时关闭数据库释放资源
  4. 对于大量写入操作,使用批量写入提高性能

以上是 BadgerDB 的基本使用方法,更多高级功能可以参考官方文档。

回到顶部