golang高性能嵌入式键值存储与数据结构插件库nutsdb的使用

Golang高性能嵌入式键值存储与数据结构插件库NutsDB的使用

什么是NutsDB?

NutsDB是一个用纯Go编写的简单、快速、可嵌入且持久化的键值存储库。它支持完全可序列化的事务和多种数据结构,如列表、集合、有序集合等。所有操作都在事务(Tx)内部进行。

架构图

nutsdb-架构图

快速开始

安装NutsDB

首先需要安装Go(1.18+版本),然后运行go get:

go get -u github.com/nutsdb/nutsdb

打开数据库

要打开数据库,使用nutsdb.Open()函数并指定适当的选项。DirEntryIdxModeSegmentSize选项必须由客户端指定。

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)
	}
}

注意事项

  1. 从v0.9.0开始,DefaultOptions中的defaultSegmentSize已从8MB调整为256MB。如果需要使用原来的默认值,需要手动更改为8MB。

  2. 在nutsdb v1.0.0之后,由于底层数据存储协议的变化,旧版本的数据不兼容。在使用新版本前需要重写数据。

  3. 当前版本的Bucket需要手动创建。


更多关于golang高性能嵌入式键值存储与数据结构插件库nutsdb的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于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
    // 如果有任何错误返回,事务将回滚
})

性能优化建议

  1. 批量操作:尽可能使用批量操作而非单条操作
  2. 合理设置Bucket:将不同类型的数据放在不同的Bucket中
  3. 控制事务大小:避免在单个事务中进行过多操作
  4. 合理设置内存模式:对于性能要求高的场景,可以考虑纯内存模式

总结

NutsDB为Go开发者提供了一个简单高效的嵌入式键值存储解决方案,支持多种数据结构和完整的事务特性。它的API设计简洁,易于集成到现有Go应用中,非常适合需要本地持久化存储但不想引入外部数据库依赖的场景。

对于更复杂的需求,还可以考虑NutsDB的TTL支持、迭代器、备份恢复等高级功能。

回到顶部