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\v2@v2.0.3\structs.go
- Stream 模式
- Merge Operations (数据合并)
- GC (垃圾回收)
- Database backup (数据备份)
- 静态加密(v2.0)
- 数据压缩(v2.0)通过使用提供的两种(zstd(需要cgo)、snappy)压缩算法之一压缩每个数据块,可以节省存储空间。仅压缩SST文件,而不压缩vlog中的文件。
badger 目录结构
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
目录结构
BadgerDB 性能测试(In-Memory Mode)
opts := badger.DefaultOptions("").WithInMemory(true)
次数 | 耗时 | 内存 | IO |
---|---|---|---|
100000 | 3s | 高(比Disk高三倍) |
备注:
- 每写入十万条记录打印一次log;
- 无论数据多少不影响后期写入;
- 540W条记录时占内存2.4G
BadgerDB 性能测试(Diskless Mode)
次数 | 耗时 | 内存 | IO | 磁盘空间 |
---|---|---|---|---|
100000 | 5s | 高(持续增长,一定时间内会释放一部分) | 4.8M/s | 1600W/5G |
LevelDB 性能测试
次数 | 耗时 | 内存 | IO | 磁盘空间 |
---|---|---|---|---|
100000 | 1.4s | 低(可以手动设置memtable) | 56.8M/s | 1600W/1.65G |
1600W记录
测试用例
leveldb测试用例
func main(){var err errordb,err = leveldb.OpenFile("D:\\db\\leveldb", nil)if err != nil {panic(err)}defer db.Close()i := 0staTime := 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 errordb, 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 := 0staTime := 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 indexletterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBitsletterIdxMax = 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 >>= letterIdxBitsremain--}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