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

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

Pudge是一个使用Go标准库编写的快速简单的键值存储库。

主要特性

  • 支持高效的查找、插入和删除操作
  • 性能与哈希表相当
  • 能够获取排序后的数据,支持范围扫描等操作
  • 支持带限制/偏移/起始键的选择查询,可按前缀或顺序查询
  • 协程安全
  • 空间高效
  • 代码简洁短小(少于500行)
  • 经过良好测试,已在生产环境使用

使用示例

package main

import (
	"log"

	"github.com/recoilme/pudge"
)

func main() {
	// 退出时关闭所有数据库
	defer pudge.CloseAll()

	// 设置值(会自动创建目录)
	pudge.Set("../test/test", "Hello", "World")

	// 获取值(如果需要会懒加载打开数据库)
	output := ""
	pudge.Get("../test/test", "Hello", &output)
	log.Println("Output:", output)

	ExampleSelect()
}

// 示例选择查询
func ExampleSelect() {
	cfg := &pudge.Config{
		SyncInterval: 1} // 每秒同步一次
	db, err := pudge.Open("../test/db", cfg)
	if err != nil {
		log.Panic(err)
	}
	defer db.DeleteFile()
	type Point struct {
		X int
		Y int
	}
	for i := 100; i >= 0; i-- {
		p := &Point{X: i, Y: i}
		db.Set(i, p)
	}
	var point Point
	db.Get(8, &point)
	log.Println(point)
	// 输出: {8 8}
	
	// 从键7开始按升序选择2个键
	keys, _ := db.Keys(7, 2, 0, true)
	for _, key := range keys {
		var p Point
		db.Get(key, &p)
		log.Println(p)
	}
	// 输出: {8 8}
	// 输出: {9 9}
}

存储任意类型数据

Pudge内部使用Gob编码器/解码器,没有键/值大小的限制。

pudge.Set("strings", "Hello", "World")
pudge.Set("numbers", 1, 42)

type User struct {
	Id int
	Name string
}
u := &User{Id: 1, Name: "name"}
pudge.Set("users", u.Id, u)

内存模式

可以通过配置使用纯内存模式:

cfg = pudge.DefaultConfig()
cfg.StoreMode = 2
db, err := pudge.Open(dbPrefix+"/"+group, cfg)
...
db.Counter(key, val)

在这种模式下,所有数据都存储在内存中,只有在Close时才会写入磁盘。

关闭处理

确保在关闭时关闭所有打开的数据库:

// 等待中断信号优雅关闭服务器
quit := make(chan os.Signal)
signal.Notify(quit, os.Interrupt, os.Kill)
<-quit
log.Println("Shutdown Server ...")
if err := pudge.CloseAll(); err != nil {
	log.Println("Pudge Shutdown err:", err)
}

备份

可以通过备份来压缩数据库:

pudge.BackupAll("backup")

性能测试

以下是一些基准测试结果(MacBook Pro Early 2015):

测试1

100万键值对,键大小16-64字节,值大小128-512字节,并发2

指标 pogreb goleveldb bolt badgerdb pudge slowpoke pudge(mem)
1M(Put+Get)秒数 187 38 126 34 23 23 2
1M Put ops/sec 5336 34743 8054 33539 47298 46789 439581
1M Get ops/sec 1782423 98406 499871 220597 499172 445783 1652069
文件大小MB 568 357 552 487 358 358 358

测试4

1000万键值对,键大小8字节,值大小16字节,并发100

指标 goleveldb badgerdb pudge
10M(Put+Get)秒数 165 120 243
10M Put ops/sec 122933 135709 43843
10M Get ops/sec 118722 214981 666067
文件大小MB 312 1370 381

Pudge在读写性能上取得了很好的平衡,适合需要高性能键值存储的场景。


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

1 回复

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


Pudge - Go语言高性能键值存储库

Pudge 是一个用纯Go编写的高性能键值存储库,它的设计目标是简单易用同时保持高性能。下面我将详细介绍Pudge的特点、使用方法和示例代码。

Pudge主要特点

  1. 简单API:类似Go的map操作方式
  2. 高性能:基于内存映射文件实现
  3. 持久化:数据自动保存到磁盘
  4. 并发安全:支持多goroutine并发访问
  5. 低内存占用:使用内存映射技术减少内存消耗

安装

go get github.com/recoilme/pudge

基本使用示例

1. 打开/创建数据库

package main

import (
	"fmt"
	"github.com/recoilme/pudge"
)

func main() {
	// 打开或创建数据库
	db, err := pudge.Open("test.db", nil)
	if err != nil {
		panic(err)
	}
	defer db.Close()
	
	// 基本操作...
}

2. CRUD操作

// 设置键值
err = db.Set("key1", "value1")
if err != nil {
    fmt.Println("Set error:", err)
}

// 获取值
var value string
err = db.Get("key1", &value)
if err != nil {
    fmt.Println("Get error:", err)
} else {
    fmt.Println("Got value:", value)
}

// 删除键
err = db.Delete("key1")
if err != nil {
    fmt.Println("Delete error:", err)
}

// 检查键是否存在
has, err := db.Has("key1")
if err != nil {
    fmt.Println("Has error:", err)
} else {
    fmt.Println("Key exists:", has)
}

3. 批量操作

// 批量设置
batch := pudge.NewBatch()
batch.Set("batch1", "value1")
batch.Set("batch2", "value2")
err = db.ExecuteBatch(batch)
if err != nil {
    fmt.Println("Batch error:", err)
}

// 遍历所有键值
db.Keys(0, 0, 0, true, func(key interface{}) bool {
    var val string
    db.Get(key, &val)
    fmt.Printf("Key: %v, Value: %s\n", key, val)
    return true // 返回true继续遍历
})

4. 高级功能

// 计数器
db.Counter("views", 1) // 增加1
var views int64
db.Get("views", &views)
fmt.Println("Total views:", views)

// 设置TTL (过期时间)
err = db.SetWithTTL("temp_key", "temp_value", 10) // 10秒后过期
if err != nil {
    fmt.Println("SetWithTTL error:", err)
}

// 使用自定义配置
cfg := &pudge.Config{
    SyncInterval: 1000, // 同步到磁盘的间隔(ms)
    FileMode:     0666, // 文件权限
    DirMode:      0777, // 目录权限
}
db, err := pudge.Open("custom.db", cfg)

性能优化建议

  1. 对于大量写入操作,使用批量写入(ExecuteBatch)
  2. 调整SyncInterval配置项平衡性能和数据安全性
  3. 避免频繁打开关闭数据库
  4. 对于热点数据可以考虑内存缓存

与BoltDB比较

Pudge相比BoltDB有以下优势:

  • 更简单的API
  • 更好的性能(特别是在写入方面)
  • 内置计数器功能
  • 内置TTL支持

完整示例

package main

import (
	"fmt"
	"log"
	"time"
	
	"github.com/recoilme/pudge"
)

func main() {
	// 打开数据库
	db, err := pudge.Open("example.db", nil)
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()
	
	// 基本操作
	err = db.Set("username", "gopher")
	if err != nil {
		log.Println("Set error:", err)
	}
	
	var username string
	err = db.Get("username", &username)
	if err != nil {
		log.Println("Get error:", err)
	} else {
		fmt.Println("Username:", username)
	}
	
	// 计数器
	for i := 0; i < 5; i++ {
		count := db.Counter("visits", 1)
		fmt.Println("Visit count:", count)
	}
	
	// 带TTL的键
	db.SetWithTTL("session_token", "abc123", 3) // 3秒后过期
	time.Sleep(1 * time.Second)
	
	var token string
	if db.Get("session_token", &token) == nil {
		fmt.Println("Token still valid:", token)
	}
	
	time.Sleep(3 * time.Second)
	if db.Get("session_token", &token) != nil {
		fmt.Println("Token expired")
	}
	
	// 遍历所有键
	fmt.Println("\nAll keys in DB:")
	db.Keys(0, 0, 0, true, func(k interface{}) bool {
		var v interface{}
		db.Get(k, &v)
		fmt.Printf("%v: %v\n", k, v)
		return true
	})
}

Pudge是一个非常适合中小型项目的键值存储解决方案,它平衡了性能、功能和易用性。对于需要更高性能或更复杂查询的场景,可以考虑结合Redis或其他专业数据库使用。

回到顶部