badger (一个高性能的LSM K/V store)使用指南
badfer是一个纯Go实现的快速的嵌入式K/V数据库,针对LSM tree做了优化。
安装
$ go get github.com/dgraph-io/badger/...
数据库
打开一个数据库
opts := badger.DefaultOptions
opts.Dir = "/tmp/badger"
opts.ValueDir = "/tmp/badger"
db, err := badger.Open(opts)
if err != nil {log.Fatal(err)
}
defer db.Close()
复制代码
存储
存储kv
使用 Txn.Set()方法
err := db.Update(func(txn *badger.Txn) error {err := txn.Set([]byte("answer"), []byte("42"))return err
})
复制代码
批量设置
wb := db.NewWriteBatch()
defer wb.Cancel()for i := 0; i < N; i++ {err := wb.Set(key(i), value(i), 0) // Will create txns as needed.handle(err)
}
handle(wb.Flush()) // Wait for all txns to finish.
复制代码
WriteBatch不允许任何读取。对于读-修改-写,应该使用事务API。
设置生存时间 TTL
Badger允许在键上设置一个可选的生存时间(TTL)值。一旦TTL结束,KEY将不再是可检索的,并且将进行垃圾收集。TTL可以使用Txn.SetWithTTL() 设置为一个time.Duration
的值
设置元数据
Txn.SetWithMeta()
设置用户元数据
使用 Txn.SetEntry()
可以一次性设置key, value, user metatadata and TTL
遍历keys
要遍历键,我们可以使用迭代器,可以使用 Txn.NewIterator()`方法获得迭代器。迭代按字节字典排序顺序进行。
err := db.View(func(txn *badger.Txn) error {opts := badger.DefaultIteratorOptionsopts.PrefetchSize = 10it := txn.NewIterator(opts)defer it.Close()for it.Rewind(); it.Valid(); it.Next() {item := it.Item()k := item.Key()err := item.Value(func(v []byte) error {fmt.Printf("key=%s, value=%s\n", k, v)return nil})if err != nil {return err}}return nil
})
复制代码
前缀扫描
要遍历键前缀,可以将Seek()和ValidForPrefix()组合使用:
db.View(func(txn *badger.Txn) error {it := txn.NewIterator(badger.DefaultIteratorOptions)defer it.Close()prefix := []byte("1234")for it.Seek(prefix); it.ValidForPrefix(prefix); it.Next() {item := it.Item()k := item.Key()err := item.Value(func(v []byte) error {fmt.Printf("key=%s, value=%s\n", k, v)return nil})if err != nil {return err}}return nil
})复制代码
键的遍历
Badger支持一种独特的迭代模式,称为只有键的迭代。它比常规迭代快几个数量级,因为它只涉及对lsm树的访问,而lsm树通常完全驻留在RAM中。要启用只有键的迭代,您需要设置IteratorOptions。PrefetchValues字段为false。这还可以用于在迭代期间对选定的键执行稀疏读取,只在需要时调用item.Value()。
err := db.View(func(txn *badger.Txn) error {opts := badger.DefaultIteratorOptionsopts.PrefetchValues = falseit := txn.NewIterator(opts)defer it.Close()for it.Rewind(); it.Valid(); it.Next() {item := it.Item()k := item.Key()fmt.Printf("key=%s\n", k)}return nil
})
复制代码
数据流
Badger提供了一个流框架,它可以并发地遍历数据库的全部或部分,将数据转换为自定义键值,并连续地将数据流输出,以便通过网络发送、写入磁盘,甚至写入Badger。这是比使用单个迭代器更快的遍历Badger的方法。Stream在管理模式和正常模式下都支持Badger。
stream := db.NewStream()
// db.NewStreamAt(readTs) for managed mode.// -- Optional settings
stream.NumGo = 16 // Set number of goroutines to use for iteration.
stream.Prefix = []byte("some-prefix") // Leave nil for iteration over the whole DB.
stream.LogPrefix = "Badger.Streaming" // For identifying stream logs. Outputs to Logger.// ChooseKey is called concurrently for every key. If left nil, assumes true by default.
stream.ChooseKey = func(item *badger.Item) bool {return bytes.HasSuffix(item.Key(), []byte("er"))
}// KeyToList is called concurrently for chosen keys. This can be used to convert
// Badger data into custom key-values. If nil, uses stream.ToList, a default
// implementation, which picks all valid key-values.
stream.KeyToList = nil// -- End of optional settings.// Send is called serially, while Stream.Orchestrate is running.
stream.Send = func(list *pb.KVList) error {return proto.MarshalText(w, list) // Write to w.
}// Run the stream
if err := stream.Orchestrate(context.Background()); err != nil {return err
}
// Done.复制代码
删除一个key
使用Txn.Delete()
方法删除一个key
获取key value
通过 txn.Get获取value
err := db.View(func(txn *badger.Txn) error {item, err := txn.Get([]byte("answer"))handle(err)var valNot, valCopy []byteerr := item.Value(func(val []byte) error {// This func with val would only be called if item.Value encounters no error.// Accessing val here is valid.fmt.Printf("The answer is: %s\n", val)// Copying or parsing val is valid.valCopy = append([]byte{}, val...)// Assigning val slice to another variable is NOT OK.valNot = val // Do not do this.return nil})handle(err)// DO NOT access val here. It is the most common cause of bugs.fmt.Printf("NEVER do this. %s\n", valNot)// You must copy it to use it outside item.Value(...).fmt.Printf("The answer is: %s\n", valCopy)// Alternatively, you could also use item.ValueCopy().valCopy, err = item.ValueCopy(nil)handle(err)fmt.Printf("The answer is: %s\n", valCopy)return nil
})
复制代码
如果不存在 Txn.Get()
将会返回一个 ErrKeyNotFound
错误
请注意,Get()返回的值只在事务打开时有效。如果需要在事务外部使用值,则必须使用copy()将其复制到另一个字节片。
事务
只读事务
只读事务使用 DB.View()方法
err := db.View(func(txn *badger.Txn) error {// Your code here…return nil
})
复制代码
读写事务锁
读写事务可以使用 DB.Update()方法
err := db.Update(func(txn *badger.Txn) error {// Your code here…return nil
})
复制代码
手动管理事务
直接使用DB.NewTransaction()
函数,手动创建和提交事务。它接受一个布尔参数来指定是否需要读写事务。对于读写事务,需要调用Txn.Commit()
来确保事务已提交。对于只读事务,调用 txn.reject()
就可以了。commit()
也在内部调用 txn .reject()
来清除事务,因此只需调用Txn.Commit()就足以执行读写事务。
但是,如果您的代码由于某种原因(出错)没有调用Txn.Commit()
。就需要在defer中调用 txn . reject()
// Start a writable transaction.
txn := db.NewTransaction(true)
defer txn.Discard()// Use the transaction...
err := txn.Set([]byte("answer"), []byte("42"))
if err != nil {return err
}// Commit the transaction and check for error.
if err := txn.Commit(); err != nil {return err
}
复制代码
本文亦在微信公众号【小道资讯】发布,欢迎扫码关注!
badger (一个高性能的LSM K/V store)使用指南相关推荐
- badger 一个高性能的LSM K/V store
大家好,给大家介绍一下, 新晋的高性能的 K/V数据库: badger. 这是 dgraph.io开发的一款基于 log structured merge (LSM) tree 的 key-value ...
- 一个key 在10w k/v 找到对应的. (B-tree), 这10w放进B-tree 会有多少层.
B-tree是二叉平衡查找树,相邻两层节点层数不超过1 所有10w 即 2^16=65536 < 10w < 2^17=131072: 会有17层,最多查询17次. 转载于:https:/ ...
- 建立一个Map实例,k值为String类型,v值为Integer类型。依次用put方法输入如下: map.put(Kobe, 24); map.put(James, 6); map.put(
建立一个Map实例,k值为String类型,v值为Integer类型.依次用put方法输入如下: map.put("Kobe", 24); map.put("James& ...
- 存储引擎 K/V 分离下的index回写问题
前言 近期在做on nvme hash引擎相关的事情,对于非全序的数据集的存储需求,相比于我们传统的LSM或者B-tree的数据结构来说 能够减少很多维护全序上的计算/存储资源.当然我们要保证hash ...
- 基于持久内存的 单机上亿(128B)QPS -- 持久化 k/v 存储引擎
文章目录 性能数据 设计背景 设计架构 Hash 索引结构 及 PMEM空间管理形态 基本API 及 实现 API 初始化流程 写流程 读流程 删除流程 PMEM Allocator设计 主要组件 空 ...
- KVell 单机k/v引擎:用最少的CPU 来调度Nvme的极致性能
文章目录 前言 KVell背景 业界引擎使用Nvme的问题 CPU 会是 LSM-kv 存储的瓶颈 CPU 也会是 Btree-kv 存储的瓶颈 KVell 设计亮点 及 总体架构实现 KVell 设 ...
- c语言map函数k v都是int,Go语言sync.Map(在并发环境中使用的map)
Go语言中的 map 在并发情况下,只读是线程安全的,同时读写是线程不安全的. 下面来看下并发情况下读写 map 时会出现的问题,代码如下: // 创建一个int到int的映射 m := make(m ...
- Ristretto 简介:一个高性能 GO 缓存
这个博客登上了 Golang subreddit[1] 的顶部,并且在 Hacker News[2] 的trending上排在前十位.一定要在那里参与讨论,并通过给我们一个 star[3],表达对我们 ...
- Ristretto 简介: 一个高性能GO缓存
Ristretto 简介: 一个高性能GO缓存 原文地址:Introducing Ristretto: A High-Performance Go Cache 原文作者:Dmitry Filimono ...
最新文章
- 接口级故障的应对方法
- 一文读懂Spring中的AOP机制
- skype安卓手机版_危险的战争游戏安卓手机版下载-危险的战争下载v1.0.13
- 科大讯飞AIUI(1)
- c++如何获取文件时间_Linux下如何删除长时间不使用的旧文件?
- 嵌入式笔录(3)-电容,频率与幅度基础
- ROS(12):双足机器人开发调研
- Laravel Carbon获取 某个时间后N个月的时间
- Go 的 Contex 是线程安全的吗?
- ibm服务器硬件故障检测工具,IBM服务器故障提示Memory/bttery problems were detected
- 暗黑主题(皮肤)资源 (实用)
- STM32应用开发实践教程:初识STM32
- android模拟器多点触摸,Windows 7 多点触摸开发模拟器和多点触摸驱动
- potplayer视频的倍速设置
- STM32Cube软件安装图文教程及视频演示
- 四元数与欧拉角之间的转换
- gbox推荐源_GBox
- 23位子网掩码是多少_24 28 30 位的子网掩码是多少
- 应用之星破除行业门槛 零成本开发手机应用
- SAP同略会:主角SAP HANA的创新口号
热门文章
- modtran matlab,modtran4软件及配套中文资料
- C#基础之数据类型Int64
- 理想国Elasticsearch入门教程
- Matlab文字球之长安十二时辰
- 企业转型谋定数字经济 李聪旭:对话中国经济和信息化
- 华为服务器安装centos找不到硬盘,华为服务器CentOS 6.6安装手册
- 将uint8_t类型的16进制字符转化转换为string字符串
- [AI-Steering编程]一.创建机车
- 关于Unity打apk包安装到有虚拟按键的android机画布被压扁解决方案
- 【机器学习系列博客】1. 维度的诅咒