youbbs
youbbs
113 0 0

Pogreb Embedded key-value store for read-heavy workloads written in Go

特点:

  • 100% Go 语言实现
  • 针对快速随机查找和不频繁的批量插入进行了优化。
  • 可以存储大于内存的数据集。
  • 内存使用率低。
  • 所有DB方法对于多个goroutine并发使用都是安全的。

这个数据库诞生的目的:

我需要一个可以将键映射到具有以下要求的值的存储:

  • 键的数量很大,我无法将这些项保存在内存中(这需要切换到更昂贵的服务器实例类型)。
  • 低延迟。如果可能的话,我想避免网络开销。
  • 我需要每天重建一次映射,然后以只读模式访问它。
  • 顺序查找性能并不重要,我只关心随机查找性能。

有很多开源的 K/V 数据库 —— 最流行的是 LevelDB、RocksDB 和 LMDB。此外,用 Go 语言实现的,例如Bolt、goleveldb 和 BadgerDB。
我尝试在生产中使用 LevelDB 和 RocksDB,但不幸的是,观察到的结果不符合性能要求。

随机读性能

随机读性能

https://github.com/akrylysov/pogreb

示例

package main

import (
	"log"

	"github.com/akrylysov/pogreb"
)

func main() {
	db, err := pogreb.Open("pogreb.test", nil)
	if err != nil {
		log.Fatal(err)
		return
	}
	defer db.Close()

	// Insert a new key-value pair.
	if err := db.Put([]byte("testKey"), []byte("testValue")); err != nil {
		log.Fatal(err)
	}
	if err := db.Put([]byte("k2"), []byte("testValue")); err != nil {
		log.Fatal(err)
	}
	if err := db.Put([]byte("k5"), []byte("testValue")); err != nil {
		log.Fatal(err)
	}
	if err := db.Put([]byte("k1"), []byte("testValue")); err != nil {
		log.Fatal(err)
	}
	if err := db.Put([]byte("k2"), []byte("testValue22")); err != nil {
		log.Fatal(err)
	}

	// Retrieve the inserted value.
	val, err := db.Get([]byte("testKey"))
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("%s", val)

	// Iterate over items.
	it := db.Items()
	for {
		key, val, err := it.Next()
		if err == pogreb.ErrIterationDone {
			break
		}
		if err != nil {
			log.Fatal(err)
		}
		log.Printf("--- %s %s", key, val)
	}
}

key 存储并不是有序的,如上例遍历,key 出现的顺序是首次保存的顺序:

2009/11/10 23:00:00 --- k2 testValue22
2009/11/10 23:00:00 --- k5 testValue
2009/11/10 23:00:00 --- k1 testValue

如果要排序,可以通过人设有序 key。

限制

由于考虑到性能,作者设计时使用 Uint32 贯穿整个架构,所以有个硬性限制是,keys 总数不能超过 42亿

缺点

由于数据结构特点,产生的数据文件特别大,实测中 150MB 的纯数据,该数据库生成的文件大小 2.2GB,而其它同类

  • 94M ./ldb (leveldb)
  • 224M ./bdb (boltdb)
0

See Also

Nearby


Discussion

Login Topics