golang高性能嵌入式键值存储与数据结构插件库nutsdb的使用
Golang高性能嵌入式键值存储与数据结构插件库NutsDB的使用
什么是NutsDB?
NutsDB是一个用纯Go编写的简单、快速、可嵌入且持久化的键值存储库。它支持完全可序列化的事务和多种数据结构,如列表、集合、有序集合等。所有操作都在事务(Tx)内部进行。
架构图
快速开始
安装NutsDB
首先需要安装Go(1.18+版本),然后运行go get:
go get -u github.com/nutsdb/nutsdb
打开数据库
要打开数据库,使用nutsdb.Open()函数并指定适当的选项。Dir
、EntryIdxMode
和SegmentSize
选项必须由客户端指定。
package main
import (
"log"
"github.com/nutsdb/nutsdb"
)
func main() {
// 打开位于/tmp/nutsdb目录中的数据库
// 如果不存在将被创建
db, err := nutsdb.Open(
nutsdb.DefaultOptions,
nutsdb.WithDir("/tmp/nutsdb"),
)
if err != nil {
log.Fatal(err)
}
defer db.Close()
...
}
完整示例Demo
下面是一个完整的NutsDB使用示例,展示了基本的键值操作:
package main
import (
"fmt"
"log"
"github.com/nutsdb/nutsdb"
)
func main() {
// 打开数据库
db, err := nutsdb.Open(
nutsdb.DefaultOptions,
nutsdb.WithDir("/tmp/nutsdb"), // 数据库目录
)
if err != nil {
log.Fatal(err)
}
defer db.Close()
// 创建bucket
bucket := "bucket1"
// 写入数据
err = db.Update(func(tx *nutsdb.Tx) error {
key := []byte("key1")
value := []byte("value1")
return tx.Put(bucket, key, value, 0) // 0表示永不过期
})
if err != nil {
log.Fatal(err)
}
// 读取数据
err = db.View(func(tx *nutsdb.Tx) error {
key := []byte("key1")
if entry, err := tx.Get(bucket, key); err != nil {
return err
} else {
fmt.Printf("Got value: %s\n", string(entry.Value))
}
return nil
})
if err != nil {
log.Fatal(err)
}
// 删除数据
err = db.Update(func(tx *nutsdb.Tx) error {
key := []byte("key1")
return tx.Delete(bucket, key)
})
if err != nil {
log.Fatal(err)
}
// 验证数据是否已删除
err = db.View(func(tx *nutsdb.Tx) error {
key := []byte("key1")
if _, err := tx.Get(bucket, key); err != nil {
if err == nutsdb.ErrKeyNotFound {
fmt.Println("Key not found (as expected after deletion)")
return nil
}
return err
}
return nil
})
if err != nil {
log.Fatal(err)
}
}
数据结构操作示例
列表(List)操作示例
func listExample(db *nutsdb.DB) {
bucket := "listBucket"
// 从列表左侧推入元素
err := db.Update(func(tx *nutsdb.Tx) error {
return tx.LPush(bucket, []byte("listKey"), []byte("value1"), []byte("value2"))
})
if err != nil {
log.Fatal(err)
}
// 从列表右侧弹出元素
err = db.Update(func(tx *nutsdb.Tx) error {
if item, err := tx.RPop(bucket, []byte("listKey")); err != nil {
return err
} else {
fmt.Printf("Popped value: %s\n", string(item))
}
return nil
})
if err != nil {
log.Fatal(err)
}
}
集合(Set)操作示例
func setExample(db *nutsdb.DB) {
bucket := "setBucket"
// 添加元素到集合
err := db.Update(func(tx *nutsdb.Tx) error {
return tx.SAdd(bucket, []byte("setKey"), []byte("member1"), []byte("member2"))
})
if err != nil {
log.Fatal(err)
}
// 检查元素是否在集合中
err = db.View(func(tx *nutsdb.Tx) error {
if ok, err := tx.SIsMember(bucket, []byte("setKey"), []byte("member1")); err != nil {
return err
} else {
fmt.Printf("Is member: %v\n", ok)
}
return nil
})
if err != nil {
log.Fatal(err)
}
}
有序集合(Sorted Set)操作示例
func sortedSetExample(db *nutsdb.DB) {
bucket := "zsetBucket"
// 添加元素到有序集合
err := db.Update(func(tx *nutsdb.Tx) error {
return tx.ZAdd(bucket, []byte("zsetKey"), 80, []byte("member1"))
})
if err != nil {
log.Fatal(err)
}
// 获取元素分数
err = db.View(func(tx *nutsdb.Tx) error {
if score, err := tx.ZScore(bucket, []byte("zsetKey"), []byte("member1")); err != nil {
return err
} else {
fmt.Printf("Score: %f\n", score)
}
return nil
})
if err != nil {
log.Fatal(err)
}
}
注意事项
-
从v0.9.0开始,
DefaultOptions
中的defaultSegmentSize
已从8MB调整为256MB。如果需要使用原来的默认值,需要手动更改为8MB。 -
在nutsdb v1.0.0之后,由于底层数据存储协议的变化,旧版本的数据不兼容。在使用新版本前需要重写数据。
-
当前版本的Bucket需要手动创建。
更多关于golang高性能嵌入式键值存储与数据结构插件库nutsdb的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang高性能嵌入式键值存储与数据结构插件库nutsdb的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
NutsDB - Go语言高性能嵌入式键值存储库
NutsDB是一个用纯Go编写的简单、快速、可嵌入的键值存储库,支持多种数据结构。它非常适合需要本地持久化存储但不想依赖外部数据库的Go应用程序。
主要特性
- 支持多种数据结构:字符串、列表、集合、有序集合、哈希
- 完全事务支持(ACID)
- 基于内存或持久化到磁盘
- 高性能
- 简单易用的API
基本使用示例
安装
go get github.com/xujiajun/nutsdb
打开数据库
package main
import (
"log"
"time"
"github.com/xujiajun/nutsdb"
)
func main() {
// 指定数据库目录
opt := nutsdb.DefaultOptions
opt.Dir = "./nutsdb_data"
// 打开数据库
db, err := nutsdb.Open(opt)
if err != nil {
log.Fatal(err)
}
defer db.Close()
// 使用数据库...
}
基本键值操作
// 写入数据
err = db.Update(func(tx *nutsdb.Tx) error {
key := []byte("name")
value := []byte("NutsDB")
return tx.Put("bucket1", key, value, 0) // 0表示永不过期
})
// 读取数据
err = db.View(func(tx *nutsdb.Tx) error {
key := []byte("name")
entry, err := tx.Get("bucket1", key)
if err != nil {
return err
}
log.Printf("Value: %s", string(entry.Value))
return nil
})
高级数据结构示例
列表(List)操作
// 列表右推
err = db.Update(func(tx *nutsdb.Tx) error {
return tx.RPush("bucket2", []byte("myList"), []byte("value1"), []byte("value2"))
})
// 列表左推
err = db.Update(func(tx *nutsdb.Tx) error {
return tx.LPush("bucket2", []byte("myList"), []byte("value0"))
})
// 获取列表范围
err = db.View(func(tx *nutsdb.Tx) error {
items, err := tx.LRange("bucket2", []byte("myList"), 0, -1)
if err != nil {
return err
}
for _, item := range items {
log.Printf("List item: %s", string(item))
}
return nil
})
集合(Set)操作
// 添加元素到集合
err = db.Update(func(tx *nutsdb.Tx) error {
return tx.SAdd("bucket3", []byte("mySet"), []byte("member1"))
})
// 检查元素是否存在
err = db.View(func(tx *nutsdb.Tx) error {
ok, err := tx.SIsMember("bucket3", []byte("mySet"), []byte("member1"))
if err != nil {
return err
}
log.Printf("Is member: %v", ok)
return nil
})
有序集合(Sorted Set)操作
// 添加元素到有序集合
err = db.Update(func(tx *nutsdb.Tx) error {
return tx.ZAdd("bucket4", []byte("myZSet"), 85.5, []byte("member1"))
})
// 获取分数范围内的元素
err = db.View(func(tx *nutsdb.Tx) error {
nodes, err := tx.ZRangeByScore("bucket4", []byte("myZSet"), 80, 90, nil)
if err != nil {
return err
}
for _, node := range nodes {
log.Printf("ZSet member: %s, score: %f", string(node.Key), node.Score)
}
return nil
})
事务处理
NutsDB支持完整的事务:
err = db.Update(func(tx *nutsdb.Tx) error {
// 事务开始
// 操作1
if err := tx.Put("bucket5", []byte("key1"), []byte("value1"), 0); err != nil {
return err
}
// 操作2
if err := tx.Put("bucket5", []byte("key2"), []byte("value2"), 0); err != nil {
return err
}
// 如果所有操作都成功,事务将提交
return nil
// 如果有任何错误返回,事务将回滚
})
性能优化建议
- 批量操作:尽可能使用批量操作而非单条操作
- 合理设置Bucket:将不同类型的数据放在不同的Bucket中
- 控制事务大小:避免在单个事务中进行过多操作
- 合理设置内存模式:对于性能要求高的场景,可以考虑纯内存模式
总结
NutsDB为Go开发者提供了一个简单高效的嵌入式键值存储解决方案,支持多种数据结构和完整的事务特性。它的API设计简洁,易于集成到现有Go应用中,非常适合需要本地持久化存储但不想引入外部数据库依赖的场景。
对于更复杂的需求,还可以考虑NutsDB的TTL支持、迭代器、备份恢复等高级功能。