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主要特点
- 简单API:类似Go的map操作方式
- 高性能:基于内存映射文件实现
- 持久化:数据自动保存到磁盘
- 并发安全:支持多goroutine并发访问
- 低内存占用:使用内存映射技术减少内存消耗
安装
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)
性能优化建议
- 对于大量写入操作,使用批量写入(
ExecuteBatch
) - 调整
SyncInterval
配置项平衡性能和数据安全性 - 避免频繁打开关闭数据库
- 对于热点数据可以考虑内存缓存
与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或其他专业数据库使用。