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)使用指南相关推荐

  1. badger 一个高性能的LSM K/V store

    大家好,给大家介绍一下, 新晋的高性能的 K/V数据库: badger. 这是 dgraph.io开发的一款基于 log structured merge (LSM) tree 的 key-value ...

  2. 一个key 在10w k/v 找到对应的. (B-tree), 这10w放进B-tree 会有多少层.

    B-tree是二叉平衡查找树,相邻两层节点层数不超过1 所有10w 即 2^16=65536 < 10w < 2^17=131072: 会有17层,最多查询17次. 转载于:https:/ ...

  3. 建立一个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& ...

  4. 存储引擎 K/V 分离下的index回写问题

    前言 近期在做on nvme hash引擎相关的事情,对于非全序的数据集的存储需求,相比于我们传统的LSM或者B-tree的数据结构来说 能够减少很多维护全序上的计算/存储资源.当然我们要保证hash ...

  5. 基于持久内存的 单机上亿(128B)QPS -- 持久化 k/v 存储引擎

    文章目录 性能数据 设计背景 设计架构 Hash 索引结构 及 PMEM空间管理形态 基本API 及 实现 API 初始化流程 写流程 读流程 删除流程 PMEM Allocator设计 主要组件 空 ...

  6. KVell 单机k/v引擎:用最少的CPU 来调度Nvme的极致性能

    文章目录 前言 KVell背景 业界引擎使用Nvme的问题 CPU 会是 LSM-kv 存储的瓶颈 CPU 也会是 Btree-kv 存储的瓶颈 KVell 设计亮点 及 总体架构实现 KVell 设 ...

  7. c语言map函数k v都是int,Go语言sync.Map(在并发环境中使用的map)

    Go语言中的 map 在并发情况下,只读是线程安全的,同时读写是线程不安全的. 下面来看下并发情况下读写 map 时会出现的问题,代码如下: // 创建一个int到int的映射 m := make(m ...

  8. Ristretto 简介:一个高性能 GO 缓存

    这个博客登上了 Golang subreddit[1] 的顶部,并且在 Hacker News[2] 的trending上排在前十位.一定要在那里参与讨论,并通过给我们一个 star[3],表达对我们 ...

  9. Ristretto 简介: 一个高性能GO缓存

    Ristretto 简介: 一个高性能GO缓存 原文地址:Introducing Ristretto: A High-Performance Go Cache 原文作者:Dmitry Filimono ...

最新文章

  1. 接口级故障的应对方法
  2. 一文读懂Spring中的AOP机制
  3. skype安卓手机版_危险的战争游戏安卓手机版下载-危险的战争下载v1.0.13
  4. 科大讯飞AIUI(1)
  5. c++如何获取文件时间_Linux下如何删除长时间不使用的旧文件?
  6. 嵌入式笔录(3)-电容,频率与幅度基础
  7. ROS(12):双足机器人开发调研
  8. Laravel Carbon获取 某个时间后N个月的时间
  9. Go 的 Contex 是线程安全的吗?
  10. ibm服务器硬件故障检测工具,IBM服务器故障提示Memory/bttery problems were detected
  11. 暗黑主题(皮肤)资源 (实用)
  12. STM32应用开发实践教程:初识STM32
  13. android模拟器多点触摸,Windows 7 多点触摸开发模拟器和多点触摸驱动
  14. potplayer视频的倍速设置
  15. STM32Cube软件安装图文教程及视频演示
  16. 四元数与欧拉角之间的转换
  17. gbox推荐源_GBox
  18. 23位子网掩码是多少_24 28 30 位的子网掩码是多少
  19. 应用之星破除行业门槛 零成本开发手机应用
  20. SAP同略会:主角SAP HANA的创新口号

热门文章

  1. modtran matlab,modtran4软件及配套中文资料
  2. C#基础之数据类型Int64
  3. 理想国Elasticsearch入门教程
  4. Matlab文字球之长安十二时辰
  5. 企业转型谋定数字经济 李聪旭:对话中国经济和信息化
  6. 华为服务器安装centos找不到硬盘,华为服务器CentOS 6.6安装手册
  7. 将uint8_t类型的16进制字符转化转换为string字符串
  8. [AI-Steering编程]一.创建机车
  9. 关于Unity打apk包安装到有虚拟按键的android机画布被压扁解决方案
  10. 【机器学习系列博客】1. 维度的诅咒