V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
yyl719133368
V2EX  ›  Go 编程语言

key value db 中的性能怪兽--badger

  •  
  •   yyl719133368 · 2018-07-04 22:13:45 +08:00 · 3383 次点击
    这是一个创建于 2360 天前的主题,其中的信息可能已经有所发展或是发生改变。

    ##key value db 中的性能怪兽--badger

    ###前言

    对于我来说今天是个值得庆祝的日子,因为本公众号迎来了很多新的朋友。在此也希望我的原创文章 能带给你们越来越多的干货,另外回答一下老铁们比较关心的问题:“是否会有从入门到精通的教程?”,我的回答是 一定会有,但不是 入门到精通 ,而是 入门到大数据项目实战 并且最近就会整理出课表分享给大家。也希望老铁们持续关注,并给我留言转发(留言可以直接给该公众号发文字消息,因为腾讯把留言功能暂时关闭了,什么时候开放暂时不清楚)。

    ###简介

    Badger

    大数据中常用到一类工具就是 key-value db,今天我就给大家介绍一下 badger, 一个可嵌入,持久,简单,快速的键值( KV )存储,并且是用纯 Go 编写(没有 CGO )。Badger 在进行随机读取时比 RocksDB 快至少 3.5 倍。 对于 128B 到 16KB 之间的数据量,数据加载速度是 RocksDB 的 0.86x - 14 倍。

    We call it Badger. Based on benchmarks, Badger is at least 3.5x faster than RocksDB when doing random reads. For value sizes between 128B to 16KB, data loading is 0.86x - 14x faster compared to RocksDB, with Badger gaining significant ground as value size increases. On the flip side, Badger is currently slower for range key-value iteration, but that has a lot of room for optimization.

    ###优势

    Badger 的优势很明显,叫它性能怪兽是有原因的:

    urthermore, during benchmarking, we found that Badger ’ s LSM tree is so small, it can easily fit in RAM. For 1KB values and 75 million 22 byte keys, the raw size of the entire dataset is 72 GB. Badger ’ s LSM tree size for this setup is a mere 1.7G, which can easily fit into RAM. This is what causes Badger ’ s random key lookup performance to be at least 3.5x faster, and Badger ’ s key-only iteration to be blazingly faster than RocksDB.

    • 随机读取速度快

    • 可直接嵌入应用

    • 使用简单方便

    • 支持多种加载模式

    • 针对 SSD 优化加成

    • 纯 Go 编写

    • 基于 LSM-tree 更小巧

    ###劣势

    劣势在官方网站上也有相关说明(如下),对于不支持集群的问题可以考虑一下 Apple 最近开源的 Foundationdb

    On the flip side, Badger is currently slower for range key-value iteration, but that has a lot of room for optimization.

    • 迭代速度比较慢

    • 不支持集群

    • 不可多个应用同时操作数据库

    ###性能

    ###应用

    ####打开数据库

    打开数据时有三种加载模式,默认模式是传统的文件 IO,:

    
    const (
       // FileIO indicates that files must be loaded using standard I/O
       FileIO FileLoadingMode = iota
       // LoadToRAM indicates that file must be loaded into RAM
       LoadToRAM
       // MemoryMap indicates that that the file must be memory-mapped
       MemoryMap
    )
    
    func GetDB(path string) *badger.DB {
       opts := badger.DefaultOptions
       opts.Dir =  path
       opts.ValueDir =  path
       opts.TableLoadingMode = options.FileIO
       db, err := badger.Open(opts)
       if err != nil {
          fmt.Println("Open db  failed:", err.Error())
          return nil
       }
       return db
    }
    

    ####set 数据

    set 数据都是以 byte 数组的形式入参,毕竟什么样的数据都可以转成[]byte,此处可以封装一下缓存来提高插入数据的效率和性能.

    
    func Set(k []byte, v []byte) {
       db.DB.Update(func(tx *badger.Txn) error {
          err := tx.Set(k, v)
          if err != nil {
             fmt.Println("Key-value db set value failed : ", err.Error())
             return err
          }
          return nil
       })
    }
    

    ####get 数据

    
    func  Get(k []byte) ([]byte, error) {
       var r []byte
       err := db.DB.View(func(tx *badger.Txn) error {
    
          item, err := tx.Get(k)
          if err != nil {
             return err
          } else {
             r, err = item.Value()
             if err != nil {
                return err
             }
          }
          return nil
       })
       return r, err
    }
    

    ####遍历数据

    遍历数据的效率其实也没有想象中那么差,100 万的数据,Key 的长度为 50 个随机字母,遍历完成的时间是 2 分 03 秒,我们项目上对这个速度已经是比较满意的啦。

    
     db.View(func(txn *badger.Txn) error {
       opts := badger.DefaultIteratorOptions
       opts.PrefetchSize = 10
       it := txn.NewIterator(opts)
       defer it.Close()
       for it.Rewind(); it.Valid(); it.Next() {
          item := it.Item()
          k := item.Key()
          v, err := item.Value()
          if err != nil {
             return err
          }
          fmt.Printf("%s  key=%s, value=%s\n",time.Now().Format("2006-01-02 15:04:05"), k, v)
       }
       return nil
    })
    

    ####Prefix

    Badger 当然也支持 Prefix 扫描遍历:

    
    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()
        v, err := item.Value()
        if err != nil {
          return err
        }
        fmt.Printf("key=%s, value=%s\n", k, v)
      }
      return nil
    })
    

    10 条回复    2018-07-05 21:56:58 +08:00
    dbow
        1
    dbow  
       2018-07-04 22:18:34 +08:00
    比 rocksdb 快? 别扯了。
    yyl719133368
        2
    yyl719133368  
    OP
       2018-07-04 22:22:16 +08:00
    @dbow 测试过?
    dbow
        3
    dbow  
       2018-07-04 22:33:24 +08:00
    rocksdb 15w/s 随机读写, 用的还是 21w iops 的渣渣 ssd。
    askfermi
        4
    askfermi  
       2018-07-04 22:58:48 +08:00 via Android
    @dbow 那 badger 是多少呢?
    dbow
        5
    dbow  
       2018-07-04 23:09:35 +08:00
    @askfermi #4 这就是个 toy project, 还有那个 boltdb, 线上一用各方面渣到哭。
    freefcw
        6
    freefcw  
       2018-07-04 23:37:47 +08:00
    @dbow bolt 的写入性能极其不好,这是和实现方式有关的。反正我比较了一把,最好还是选择了 rocksdb.badger 这个玩具真的还是不太适合线上,印象中性能也不怎么滴
    yyl719133368
        7
    yyl719133368  
    OP
       2018-07-05 07:29:56 +08:00
    bolt 是坚决不能用的,

    ![]( http://pba3xgxbt.bkt.clouddn.com/18-7-5/46127715.jpg)
    Reign
        8
    Reign  
       2018-07-05 14:20:17 +08:00
    php 怎么用?
    line
        9
    line  
       2018-07-05 15:47:41 +08:00
    那有什么推荐的吗?
    @freefcw
    @dbow
    freefcw
        10
    freefcw  
       2018-07-05 21:56:58 +08:00
    @line rocksdb,比较成熟稳定
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1750 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 16:35 · PVG 00:35 · LAX 08:35 · JFK 11:35
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.