绑定完请刷新页面
取消
刷新

分享好友

×
取消 复制
badger (一个高性能的LSM K/V store)使用指南
2022-04-15 15:44:33

badfer是一个纯Go实现的快速的嵌入式K/V数据库,针对LSM tree做了优化。

安装

$ go get github.com/dgraph-io/badger/...

数据库

打开一个数据库

  1. opts := badger.DefaultOptions
  2. opts.Dir = "/tmp/badger"
  3. opts.ValueDir = "/tmp/badger"
  4. db, err := badger.Open(opts)
  5. if err != nil {
  6. log.Fatal(err)
  7. }
  8. defer db.Close()
  9. 复制代码

存储

存储kv

使用 Txn.Set()方法

  1. err := db.Update(func(txn *badger.Txn) error {
  2. err := txn.Set([]byte("answer"), []byte("42"))
  3. return err
  4. })
  5. 复制代码

批量设置

  1. wb := db.NewWriteBatch()
  2. defer wb.Cancel()
  3. for i := 0; i < N; i++ {
  4. err := wb.Set(key(i), value(i), 0) // Will create txns as needed.
  5. handle(err)
  6. }
  7. handle(wb.Flush()) // Wait for all txns to finish.
  8. 复制代码

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()`方法获得迭代器。迭代按字节字典排序顺序进行。

  1. err := db.View(func(txn *badger.Txn) error {
  2. opts := badger.DefaultIteratorOptions
  3. opts.PrefetchSize = 10
  4. it := txn.NewIterator(opts)
  5. defer it.Close()
  6. for it.Rewind(); it.Valid(); it.Next() {
  7. item := it.Item()
  8. k := item.Key()
  9. err := item.Value(func(v []byte) error {
  10. fmt.Printf("key=%s, value=%s\n", k, v)
  11. return nil
  12. })
  13. if err != nil {
  14. return err
  15. }
  16. }
  17. return nil
  18. })
  19. 复制代码

前缀扫描

要遍历键前缀,可以将Seek()和ValidForPrefix()组合使用:

  1. db.View(func(txn *badger.Txn) error {
  2. it := txn.NewIterator(badger.DefaultIteratorOptions)
  3. defer it.Close()
  4. prefix := []byte("1234")
  5. for it.Seek(prefix); it.ValidForPrefix(prefix); it.Next() {
  6. item := it.Item()
  7. k := item.Key()
  8. err := item.Value(func(v []byte) error {
  9. fmt.Printf("key=%s, value=%s\n", k, v)
  10. return nil
  11. })
  12. if err != nil {
  13. return err
  14. }
  15. }
  16. return nil
  17. })
  18. 复制代码

键的遍历

Badger支持一种独特的迭代模式,称为只有键的迭代。它比常规迭代快几个数量级,因为它只涉及对lsm树的访问,而lsm树通常完全驻留在RAM中。要启用只有键的迭代,您需要设置IteratorOptions。PrefetchValues字段为false。这还可以用于在迭代期间对选定的键执行稀疏读取,只在需要时调用item.Value()。

  1. err := db.View(func(txn *badger.Txn) error {
  2. opts := badger.DefaultIteratorOptions
  3. opts.PrefetchValues = false
  4. it := txn.NewIterator(opts)
  5. defer it.Close()
  6. for it.Rewind(); it.Valid(); it.Next() {
  7. item := it.Item()
  8. k := item.Key()
  9. fmt.Printf("key=%s\n", k)
  10. }
  11. return nil
  12. })
  13. 复制代码

数据流

Badger提供了一个流框架,它可以并发地遍历数据库的全部或部分,将数据转换为自定义键值,并连续地将数据流输出,以便通过网络发送、写入磁盘,甚至写入Badger。这是比使用单个迭代器更快的遍历Badger的方法。Stream在管理模式和正常模式下都支持Badger。

  1. stream := db.NewStream()
  2. // db.NewStreamAt(readTs) for managed mode.
  3. // -- Optional settings
  4. stream.NumGo = 16 // Set number of goroutines to use for iteration.
  5. stream.Prefix = []byte("some-prefix") // Leave nil for iteration over the whole DB.
  6. stream.LogPrefix = "Badger.Streaming" // For identifying stream logs. Outputs to Logger.
  7. // ChooseKey is called concurrently for every key. If left nil, assumes true by default.
  8. stream.ChooseKey = func(item *badger.Item) bool {
  9. return bytes.HasSuffix(item.Key(), []byte("er"))
  10. }
  11. // KeyToList is called concurrently for chosen keys. This can be used to convert
  12. // Badger data into custom key-values. If nil, uses stream.ToList, a default
  13. // implementation, which picks all valid key-values.
  14. stream.KeyToList = nil
  15. // -- End of optional settings.
  16. // Send is called serially, while Stream.Orchestrate is running.
  17. stream.Send = func(list *pb.KVList) error {
  18. return proto.MarshalText(w, list) // Write to w.
  19. }
  20. // Run the stream
  21. if err := stream.Orchestrate(context.Background()); err != nil {
  22. return err
  23. }
  24. // Done.
  25. 复制代码

删除一个key

使用Txn.Delete() 方法删除一个key

获取key value

通过 txn.Get获取value

  1. err := db.View(func(txn *badger.Txn) error {
  2. item, err := txn.Get([]byte("answer"))
  3. handle(err)
  4. var valNot, valCopy []byte
  5. err := item.Value(func(val []byte) error {
  6. // This func with val would only be called if item.Value encounters no error.
  7. // Accessing val here is valid.
  8. fmt.Printf("The answer is: %s\n", val)
  9. // Copying or parsing val is valid.
  10. valCopy = append([]byte{}, val...)
  11. // Assigning val slice to another variable is NOT OK.
  12. valNot = val // Do not do this.
  13. return nil
  14. })
  15. handle(err)
  16. // DO NOT access val here. It is the most common cause of bugs.
  17. fmt.Printf("NEVER do this. %s\n", valNot)
  18. // You must copy it to use it outside item.Value(...).
  19. fmt.Printf("The answer is: %s\n", valCopy)
  20. // Alternatively, you could also use item.ValueCopy().
  21. valCopy, err = item.ValueCopy(nil)
  22. handle(err)
  23. fmt.Printf("The answer is: %s\n", valCopy)
  24. return nil
  25. })
  26. 复制代码

如果不存在 Txn.Get() 将会返回一个 ErrKeyNotFound 错误

请注意,Get()返回的值只在事务打开时有效。如果需要在事务外部使用值,则必须使用copy()将其复制到另一个字节片。

事务

只读事务

只读事务使用 DB.View()方法

  1. err := db.View(func(txn *badger.Txn) error {
  2. // Your code here…
  3. return nil
  4. })
  5. 复制代码

读写事务锁

读写事务可以使用 DB.Update()方法

  1. err := db.Update(func(txn *badger.Txn) error {
  2. // Your code here…
  3. return nil
  4. })
  5. 复制代码

手动管理事务

直接使用DB.NewTransaction()函数,手动创建和提交事务。它接受一个布尔参数来指定是否需要读写事务。对于读写事务,需要调用Txn.Commit()来确保事务已提交。对于只读事务,调用 txn.reject()就可以了。commit()也在内部调用 txn .reject()来清除事务,因此只需调用Txn.Commit()就足以执行读写事务。

但是,如果您的代码由于某种原因(出错)没有调用Txn.Commit()。就需要在defer中调用 txn . reject()

  1. // Start a writable transaction.
  2. txn := db.NewTransaction(true)
  3. defer txn.Discard()
  4. // Use the transaction...
  5. err := txn.Set([]byte("answer"), []byte("42"))
  6. if err != nil {
  7. return err
  8. }
  9. // Commit the transaction and check for error.
  10. if err := txn.Commit(); err != nil {
  11. return err
  12. }
  13. 复制代码

来源 https://blog.csdn.net/weixin_33796205/article/details/91366048?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165000820316780264017263%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=165000820316780264017263&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-3-91366048.142^v9^control,157^v4^new_style&utm_term=Badger&spm=1018.2226.3001.4449

分享好友

分享这个小栈给你的朋友们,一起进步吧。

Badger
创建时间:2022-04-15 15:34:19
Badger
展开
订阅须知

• 所有用户可根据关注领域订阅专区或所有专区

• 付费订阅:虚拟交易,一经交易不退款;若特殊情况,可3日内客服咨询

• 专区发布评论属默认订阅所评论专区(除付费小栈外)

技术专家

查看更多
  • itt0918
    专家
戳我,来吐槽~