• Badger简单使用


    Badger简介

    badger 是 dgraph 开源的 LSMTree 的 KV 引擎,它相比 leveldb 有 KV 分离、事务、并发合并等增强,是 go 生态中比较生产级的存储引擎了。

    文档:https://dgraph.io/docs/badger/get-started/

    Github 地址:https://github.com/dgraph-io/badger

    安装

    安装 Badger

    要开始使用 Badger,请安装 Go 1.12 或更高版本。

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

    注意:Badger 不直接使用 CGO,但它依赖于https://github.com/DataDog/zstd进行压缩,并且需要 gcc/cgo。如果你想在没有 gcc/cgo 的情况下使用 badger,你可以运行CGO_ENABLED=0 go get github.com/dgraph-io/badger/…它将下载不支持 ZSTD 压缩算法的 badger。

    安装 Badger 命令行工具

    https://github.com/dgraph-io/badger/releases 下载并提取最新的 Badger DB 版本,然后运行以下命令。

    cd badger-<version>/badger
    go install
    

    这会将 badger 命令行实用程序安装到您的 $GOBIN 路径中。

    数据库操作

    打开数据库

    func Open(path string) (*badger.DB, error) {
    	if _, err := os.Stat(path); os.IsNotExist(err) {
    		os.MkdirAll(path, 0755)
    	}
    	opts := badger.DefaultOptions(path)
    	opts.Dir = path
    	opts.ValueDir = path
    	opts.SyncWrites = false
    	opts.ValueThreshold = 256
    	opts.CompactL0OnClose = true
    	db, err := badger.Open(opts)
    	if err != nil {
    		log.Println("badger open failed", "path", path, "err", err)
    		return nil, err
    	}
    	return db, nil
    }
    

    内存模式/无盘模式

    默认情况下,Badger 确保所有数据都保存在磁盘上。它还支持纯内存模式。当 Badger 在内存模式下运行时,所有数据都存储在内存中。在内存模式下读写速度要快得多,但在崩溃或关闭的情况下,存储在 Badger 中的所有数据都会丢失。要在内存模式下打开 badger,请设置InMemory选项。

    opts := badger.DefaultOptions(path).WithInMemory(true)
    

    关闭数据库

    func Close() {
    	err := badgerDB.Close()
    	if err == nil {
    		log.Println("database closed", "err", err)
    	} else {
    		log.Println("failed to close database", "err", err)
    	}
    }
    

    存储操作

    写入数据

    要保存键/值对,请使用以下Txn.Set()方法;

    键/值对也可以通过首先创建来保存Entry,然后 Entry使用Txn.SetEntry(). Entry还公开了在其上设置属性的方法。

    func Set(key []byte, value []byte) {
    	wb := badgerDB.NewWriteBatch()
    	defer wb.Cancel()
    	err := wb.SetEntry(badger.NewEntry(key, value).WithMeta(0))
    	if err != nil {
    		log.Println("Failed to write data to cache.","key", string(key), "value", string(value), "err", err)
    	}
    	err = wb.Flush()
    	if err != nil {
    		log.Println("Failed to flush data to cache.","key", string(key), "value", string(value), "err", err)
    	}
    }
    

    设置TTL的写入数据

    Badger 允许在键上设置可选的生存时间 (TTL) 值。一旦 TTL 过去,密钥将不再可检索,并且将有资格进行垃圾收集。 可以使用和API 方法将 TTL 设置为time.Duration值。Entry.WithTTL() Txn.SetEntry()

    func SetWithTTL(key []byte, value []byte, ttl int64) {
    	wb := badgerDB.NewWriteBatch()
    	defer wb.Cancel()
    	err := wb.SetEntry(badger.NewEntry(key, value).WithMeta(0).WithTTL(time.Duration(ttl * time.Second.Nanoseconds())))
    	if err != nil {
    		log.Println("Failed to write data to cache.","key", string(key), "value", string(value), "err", err)
    	}
    	err = wb.Flush()
    	if err != nil {
    		log.Println("Failed to flush data to cache.","key", string(key), "value", string(value), "err", err)
    	}
    }
    

    读取数据

    要读取数据,我们可以使用以下Txn.Get()方法。

    func Get(key []byte) string {
    	var ival []byte
    	err := badgerDB.View(func(txn *badger.Txn) error {
    		item, err := txn.Get(key)
    		if err != nil {
    			return err
    		}
    		ival, err = item.ValueCopy(nil)
    		return err
    	})
    	if err != nil {
    		log.Println("Failed to read data from the cache.","key", string(key), "error", err)
    	}
    	return string(ival)
    }
    

    存在键

    func Has(key []byte) (bool, error) {
    	var exist bool = false
    	err := badgerDB.View(func(txn *badger.Txn) error {
    		_, err := txn.Get(key)
    		if err != nil {
    			return err
    		} else {
    			exist = true
    		}
    		return err
    	})
    	// align with leveldb, if the key doesn't exist, leveldb returns nil
    	if strings.HasSuffix(err.Error(), "not found") {
    		err = nil
    	}
    	return exist, err
    }
    

    删除键

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

    func Delete(key []byte) error {
    	wb := badgerDB.NewWriteBatch()
    	defer wb.Cancel()
    	return wb.Delete(key)
    }
    

    查询操作

    遍历key和value

    要迭代键,我们可以使用Iterator,可以使用 Txn.NewIterator()方法获得。迭代以按字节排序的字典顺序发生。

    func IteratorKeysAndValues(){
    
    	err := badgerDB.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()
    			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
    	})
    	if err != nil {
    		log.Println("Failed to iterator keys and values from the cache.","error", err)
    	}
    }
    

    遍历keys

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

    func IteratorKeys(){
        err := badgerDB.View(func(txn *badger.Txn) error {
            opts := badger.DefaultIteratorOptions
            opts.PrefetchValues = false
            it := 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
        })
    
        if err != nil {
            log.Println("Failed to iterator keys from the cache.","error", err)
        }
    }
    

    前缀扫描

    要遍历一个键前缀,您可以组合Seek()and ValidForPrefix()

    func SeekWithPrefix(prefixStr string){
    	err := badgerDB.View(func(txn *badger.Txn) error {
    		it := txn.NewIterator(badger.DefaultIteratorOptions)
    		defer it.Close()
    		prefix := []byte(prefixStr)
    		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
    	})
    	if err != nil {
    		log.Println("Failed to seek prefix from the cache.", "prefix", prefixStr,"error", err)
    	}
    }
    

    原文链接:https://weixiaodyanlei.xyz/archives/badger-jian-dan-shi-yong

  • 相关阅读:
    20道经典Java面试基础题
    修改vscode底部栏背景和字体颜色
    UML反刍
    数据结构——红黑树
    QTcpServer 封装
    Docker构建jar包镜像并运行容器
    Ubuntu20.04 搭建L2TP+IPsec客户端
    android的rtmp直播推流(一) nginx服务器的搭建
    docker部署Vaultwarden密码共享管理系统
    经济师报考专业选择及难度分析!这三个专业每年报考人数超10万!
  • 原文地址:https://www.cnblogs.com/dawn-lewis/p/16055348.html