Badger、Leveldb

BadgerDB v2 介绍

2017年发行 来自DGraph实验室 开源 纯go语言编写
https://github.com/dgraph-io/badger
https://godoc.org/github.com/dgraph-io/badger

  • 内存模式 (所有数据存在内存,可能丢失数据)
  • SSD优化
  • 键值分离 Key(00000*.sst) Value 分开存储(00000*.vlog)
    • SSTable存储结构kv是存在一起的, badger中v存的是指针,真正的value存在.vlog中
    • github.com\dgraph-io\badger\[email protected]\structs.goBadger、Leveldb_第1张图片
  • Stream 模式
  • Merge Operations (数据合并)
  • GC (垃圾回收)
  • Database backup (数据备份)
  • 静态加密(v2.0)
  • 数据压缩(v2.0)通过使用提供的两种(zstd(需要cgo)、snappy)压缩算法之一压缩每个数据块,可以节省存储空间。仅压缩SST文件,而不压缩vlog中的文件。

badger 目录结构
Badger、Leveldb_第2张图片

LevelDB 介绍

2011年发行 来自Google实验室 开源 发行于C++,GO复写
https://github.com/google/leveldb (C++版本)
https://github.com/syndtr/goleveldb(GO版本)
https://godoc.org/github.com/syndtr/goleveldb/leveldb
目录结构
Badger、Leveldb_第3张图片

BadgerDB 性能测试(In-Memory Mode)

opts := badger.DefaultOptions("").WithInMemory(true)
次数 耗时 内存 IO
100000 3s 高(比Disk高三倍)

Badger、Leveldb_第4张图片
Badger、Leveldb_第5张图片
备注:

  • 每写入十万条记录打印一次log;
  • 无论数据多少不影响后期写入;
  • 540W条记录时占内存2.4G

BadgerDB 性能测试(Diskless Mode)

次数 耗时 内存 IO 磁盘空间
100000 5s 高(持续增长,一定时间内会释放一部分) 4.8M/s 1600W/5G

Badger、Leveldb_第6张图片
Badger、Leveldb_第7张图片
Badger、Leveldb_第8张图片

LevelDB 性能测试

次数 耗时 内存 IO 磁盘空间
100000 1.4s 低(可以手动设置memtable) 56.8M/s 1600W/1.65G

Badger、Leveldb_第9张图片
1600W记录Badger、Leveldb_第10张图片

测试用例

leveldb测试用例

func main(){
	var err error
	db,err = leveldb.OpenFile("D:\\db\\leveldb", nil)
	if err != nil {
		panic(err)
	}
	defer db.Close()

	i := 0
	staTime := time.Now()
	for {
		Add(utils.RandStringBytesMaskImprSrcUnsafe(32), utils.RandStringBytesMaskImprSrcUnsafe(64));
		i++

		if i % 100000 == 0 {
			fmt.Printf("number:%v,time:%v\n",i,time.Since(staTime))
			staTime = time.Now()
		}
	}
}

func Add(key []byte ,value []byte){
	db.Put(key, value, nil)
}

badger 测试用例

func main() {
	var err error
	db, err = badger.Open(badger.DefaultOptions("D:\\db\\badger"))
	//内存模式
	//db, err = badger.Open(badger.DefaultOptions("").WithInMemory(true))
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()


	i := 0
	staTime := time.Now()
	for {
		Set(utils.RandStringBytesMaskImprSrcUnsafe(32),utils.RandStringBytesMaskImprSrcUnsafe(64))
		i++

		if i % 100000 == 0 {
			//var m runtime.MemStats
			//runtime.ReadMemStats(&m)
			//fmt.Printf("%d Kb\n",m.Alloc/1024)

			fmt.Printf("number:%v,ageTime:%v\n",i,time.Since(staTime))
			staTime = time.Now()
		}
	}
}

func Set(key []byte,value []byte) {
	db.Update(func(txn *badger.Txn) error {
		return txn.Set(key, value)
	})
}

生成随机数

const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
const (
	letterIdxBits = 6                    // 6 bits to represent a letter index
	letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
	letterIdxMax  = 63 / letterIdxBits   // # of letter indices fitting in 63 bits
)

var src = rand.NewSource(time.Now().UnixNano())
//生成随机数
func RandStringBytesMaskImprSrcUnsafe(n int) []byte {
	b := make([]byte, n)
	// A src.Int63() generates 63 random bits, enough for letterIdxMax characters!
	for i, cache, remain := n-1, src.Int63(), letterIdxMax; i >= 0; {
		if remain == 0 {
			cache, remain = src.Int63(), letterIdxMax
		}
		if idx := int(cache & letterIdxMask); idx < len(letterBytes) {
			b[i] = letterBytes[idx]
			i--
		}
		cache >>= letterIdxBits
		remain--
	}

	return b
}

Benchmark test

leveldb testcase

func BenchmarkAdd(b *testing.B) {
	defer db.Close()
	//重置时间
	b.ResetTimer()
	//所有基准测试函数
	b.ReportAllocs()

	for i:=0; i <= b.N; i++{
		Add(utils.RandStringBytesMaskImprSrcUnsafe(32), utils.RandStringBytesMaskImprSrcUnsafe(64));
	}
}


//预先随机生成100个CEhxvNeqSJBvjIUObHQSTUhkFGGrcnaj+n的key
func BenchmarkGet(b *testing.B) {
	defer db.Close()
	//重置时间
	b.ResetTimer()
	//所有基准测试函数
	b.ReportAllocs()
	for i:=0; i <= b.N; i++{
		Get(fmt.Sprintf("%s%v", "CEhxvNeqSJBvjIUObHQSTUhkFGGrcnaj", utils.RandInt()))
	}
}

goos: windows
goarch: amd64
pkg: github.com/hyperledger/db_case/leveldb
BenchmarkAdd
BenchmarkAdd-8 1948048 610 ns/op 96 B/op 2 allocs/op
PASS

goos: windows
goarch: amd64
pkg: github.com/hyperledger/db_case/leveldb
BenchmarkGet
BenchmarkGet-8 80000 14400 ns/op 912 B/op 14 allocs/op
PASS

badger testcase

func BenchmarkSet(b *testing.B) {
	//重置时间
	b.ResetTimer()
	//所有基准测试函数
	b.ReportAllocs()
	for i:=0; i <= b.N; i++{
		Set(utils.RandStringBytesMaskImprSrcUnsafe(32),utils.RandStringBytesMaskImprSrcUnsafe(64))
	}
}
//预先随机生成100个CEhxvNeqSJBvjIUObHQSTUhkFGGrcnaj+n的key
func BenchmarkGet(b *testing.B) {
	defer db.Close()
	//重置时间
	b.ResetTimer()
	//所有基准测试函数
	b.ReportAllocs()
	for i:=0; i <= b.N; i++{
		Get(fmt.Sprintf("%s%v", "CEhxvNeqSJBvjIUObHQSTUhkFGGrcnaj", utils.RandInt()))
	}
}

goos: windows
goarch: amd64
pkg: github.com/hyperledger/db_case/badger
BenchmarkSet
BenchmarkSet-8 23300 48224 ns/op 2372 B/op 72 allocs/op
PASS

badger 2020/04/01 23:22:43 INFO: All 0 tables opened in 0s
badger 2020/04/01 23:22:43 INFO: Replaying file id: 0 at offset: 0
badger 2020/04/01 23:22:43 INFO: Replay took: 138.006ms
badger 2020/04/01 23:22:43 DEBUG: Value log discard stats empty
goos: windows
goarch: amd64
pkg: github.com/hyperledger/db_case/badger
BenchmarkGet
BenchmarkGet-8 85722 15025 ns/op 455 B/op 8 allocs/op
PASS

100w 写入测试
badger

BenchmarkSet-8 1000000 52995 ns/op 2621 B/op 72 allocs/op

leveldb

BenchmarkAdd-8 1000000 13236 ns/op 258 B/op 5 allocs/op

关于win系统出现 Value log truncate required to run DB. This might result in data loss 。

https://github.com/dgraph-io/badger/pull/1134
https://github.com/dgraph-io/badger/issues/1126

你可能感兴趣的:(badger,go)