golang常用库之-KV数据库之pebble

文章目录

  • golang常用库之-KV数据库之pebble
    • pebble
      • 官方示例代码
    • 实战
    • pebble常用方法
      • NewSnapshot方法
      • NewIndexedBatch 方法
    • 参考

golang常用库之-KV数据库之pebble

rocksdb是一款由Facebook使用C/C++开发的嵌入式的持久化的KV数据库。

Pebble 是 Cockroach 参考 RocksDB 并用 Go 语言开发的高性能 KV 存储引擎。

pebble

github地址:https://github.com/cockroachdb/pebble

Pebble 是一个受 LevelDB/RocksDB 启发的键值存储,专注于 CockroachDB 的性能和内部使用。Pebble 继承了 RocksDB 文件格式和一些扩展名,例如范围删除逻辑删除、表级绽放过滤器和 MANIFEST 格式更新。

Pebble 有意不追求在 RocksDB 中包含所有功能,而是专门针对 CockroachDB 所需的用例和功能集, RocksDB 有大量 Pebble 中没有实现的功能。

Pebble 对 RocksDB 进行了多项改进!

Pebble 在 CockroachDB v20.1(2020 年 5 月发布)中作为 RocksDB 的替代存储引擎引入,并在当时成功用于生产。Pebble 在 CockroachDB v20.2(2020 年 11 月发布)中成为默认存储引擎。Pebble 正在被 CockroachDB 的用户大规模地用于生产,并且被认为是稳定且可用于生产的。

官方示例代码

package mainimport ("fmt""log""github.com/cockroachdb/pebble"
)func main() {db, err := pebble.Open("demo", &pebble.Options{})if err != nil {log.Fatal(err)}key := []byte("hello")if err := db.Set(key, []byte("world"), pebble.Sync); err != nil {log.Fatal(err)}value, closer, err := db.Get(key)if err != nil {log.Fatal(err)}fmt.Printf("%s %s\n", key, value)if err := closer.Close(); err != nil {log.Fatal(err)}if err := db.Close(); err != nil {log.Fatal(err)}
}

实战

来自项目https://github.com/NethermindEth/juno
db/pebble/db.go

package pebbleimport ("sync""testing""github.com/NethermindEth/juno/db""github.com/NethermindEth/juno/utils""github.com/cockroachdb/pebble""github.com/cockroachdb/pebble/vfs"
)const (// minCache is the minimum amount of memory in megabytes to allocate to pebble read and write caching.minCache = 8
)var _ db.DB = (*DB)(nil)type DB struct {pebble   *pebble.DBwMutex   *sync.Mutexlistener db.EventListener
}// New opens a new database at the given path
func New(path string, cache uint, maxOpenFiles int, logger pebble.Logger) (db.DB, error) {// Ensure that the specified cache size meets a minimum threshold.cache = max(minCache, cache)pDB, err := newPebble(path, &pebble.Options{Logger:       logger,Cache:        pebble.NewCache(int64(cache * utils.Megabyte)),MaxOpenFiles: maxOpenFiles,})if err != nil {return nil, err}return pDB, nil
}// NewMem opens a new in-memory database
func NewMem() (db.DB, error) {return newPebble("", &pebble.Options{FS: vfs.NewMem(),})
}// NewMemTest opens a new in-memory database, panics on error
func NewMemTest(t *testing.T) db.DB {memDB, err := NewMem()if err != nil {t.Fatalf("create in-memory db: %v", err)}t.Cleanup(func() {if err := memDB.Close(); err != nil {t.Errorf("close in-memory db: %v", err)}})return memDB
}func newPebble(path string, options *pebble.Options) (*DB, error) {pDB, err := pebble.Open(path, options)if err != nil {return nil, err}return &DB{pebble: pDB, wMutex: new(sync.Mutex), listener: &db.SelectiveListener{}}, nil
}// WithListener registers an EventListener
func (d *DB) WithListener(listener db.EventListener) db.DB {d.listener = listenerreturn d
}// NewTransaction : see db.DB.NewTransaction
func (d *DB) NewTransaction(update bool) (db.Transaction, error) {txn := &Transaction{listener: d.listener,}if update {d.wMutex.Lock()txn.lock = d.wMutextxn.batch = d.pebble.NewIndexedBatch()} else {txn.snapshot = d.pebble.NewSnapshot()}return txn, nil
}// Close : see io.Closer.Close
func (d *DB) Close() error {return d.pebble.Close()
}// View : see db.DB.View
func (d *DB) View(fn func(txn db.Transaction) error) error {return db.View(d, fn)
}// Update : see db.DB.Update
func (d *DB) Update(fn func(txn db.Transaction) error) error {return db.Update(d, fn)
}// Impl : see db.DB.Impl
func (d *DB) Impl() any {return d.pebble
}
  • DB 结构体:

    • pebble: Pebble 数据库的实例。
    • wMutex: 用于控制写操作的互斥锁。
    • listener: 数据库事件监听器。
  • New 函数:

    • 用于打开一个给定路径的数据库。
    • 确保指定的缓存大小满足最小阈值要求。
    • 创建一个新的 Pebble 实例,并返回数据库实例。
  • newPebble 函数: 用于创建一个新的 Pebble 实例

func newPebble(path string, options *pebble.Options) (*DB, error) {pDB, err := pebble.Open(path, options)if err != nil {return nil, err}return &DB{pebble: pDB, wMutex: new(sync.Mutex), listener: &db.SelectiveListener{}}, nil
}

使用 pebble.Open 函数打开一个 Pebble 数据库,传入给定的路径和选项。
如果打开成功,则创建一个新的 DB 结构体实例,并初始化其中的字段:
pebble 字段使用刚刚打开的 Pebble 数据库实例。
wMutex 字段为一个新的互斥锁。
listener 字段为一个新的 db.SelectiveListener 实例的指针。

  • WithListener 方法:
    用于注册一个事件监听器。
  • Close: 关闭数据库。
  • View: 执行数据库的只读操作。
  • Update: 执行数据库的读写操作。
  • Impl: 返回底层的 Pebble 实例。
  • NewTransaction: 创建一个新的事务。
    NewTransaction 比较特殊是自定义业务有关的方法, “NewTransaction 返回一个在该数据库上的事务。如果请求创建一个更新事务,而另一个更新事务正在进行中,那么该方法应该会被阻塞。”
func (d *DB) NewTransaction(update bool) (db.Transaction, error) {txn := &Transaction{listener: d.listener,}if update {d.wMutex.Lock()txn.lock = d.wMutextxn.batch = d.pebble.NewIndexedBatch()} else {txn.snapshot = d.pebble.NewSnapshot()}return txn, nil
}
  • 如果 update 为 true,则表示创建一个更新事务。此时,会获取 DB 对象的写入互斥锁 wMutex,将该互斥锁赋给事务对象的 lock 字段,并使用 Pebble 数据库的 NewIndexedBatch 方法创建一个新的批处理对象,并将其赋给事务对象的 batch 字段。
  • 如果 update 为 false,则表示创建一个只读事务。此时,会使用 Pebble 数据库的 NewSnapshot 方法创建一个新的快照对象,并将其赋给事务对象的 snapshot 字段。

这样做的目的是为了保证数据库的一致性和隔离性。如果多个更新事务同时进行,可能会导致数据库状态出现不一致的情况。通过阻塞方式,可以确保同一时间只有一个更新事务在进行。

db/pebble/transaction.go

package pebbleimport ("errors""io""sync""time""github.com/NethermindEth/juno/db""github.com/NethermindEth/juno/utils""github.com/cockroachdb/pebble"
)var ErrDiscardedTransaction = errors.New("discarded txn")var _ db.Transaction = (*Transaction)(nil)type Transaction struct {batch    *pebble.Batchsnapshot *pebble.Snapshotlock     *sync.Mutexlistener db.EventListener
}// Discard : see db.Transaction.Discard
func (t *Transaction) Discard() error {if t.batch != nil {if err := t.batch.Close(); err != nil {return err}t.batch = nil}if t.snapshot != nil {if err := t.snapshot.Close(); err != nil {return err}t.snapshot = nil}if t.lock != nil {t.lock.Unlock()t.lock = nil}return nil
}// Commit : see db.Transaction.Commit
func (t *Transaction) Commit() error {start := time.Now()defer func() { t.listener.OnCommit(time.Since(start)) }()if t.batch != nil {return utils.RunAndWrapOnError(t.Discard, t.batch.Commit(pebble.Sync))}return utils.RunAndWrapOnError(t.Discard, ErrDiscardedTransaction)
}// Set : see db.Transaction.Set
func (t *Transaction) Set(key, val []byte) error {start := time.Now()if t.batch == nil {return errors.New("read only transaction")}if len(key) == 0 {return errors.New("empty key")}defer func() { t.listener.OnIO(true, time.Since(start)) }()return t.batch.Set(key, val, pebble.Sync)
}// Delete : see db.Transaction.Delete
func (t *Transaction) Delete(key []byte) error {start := time.Now()if t.batch == nil {return errors.New("read only transaction")}defer func() { t.listener.OnIO(true, time.Since(start)) }()return t.batch.Delete(key, pebble.Sync)
}// Get : see db.Transaction.Get
func (t *Transaction) Get(key []byte, cb func([]byte) error) error {start := time.Now()var val []bytevar closer io.Closervar err errorif t.batch != nil {val, closer, err = t.batch.Get(key)} else if t.snapshot != nil {val, closer, err = t.snapshot.Get(key)} else {return ErrDiscardedTransaction}defer t.listener.OnIO(false, time.Since(start))if err != nil {if errors.Is(err, pebble.ErrNotFound) {return db.ErrKeyNotFound}return err}return utils.RunAndWrapOnError(closer.Close, cb(val))
}// Impl : see db.Transaction.Impl
func (t *Transaction) Impl() any {if t.batch != nil {return t.batch}if t.snapshot != nil {return t.snapshot}return nil
}// NewIterator : see db.Transaction.NewIterator
func (t *Transaction) NewIterator() (db.Iterator, error) {var (iter *pebble.Iteratorerr  error)if t.batch != nil {iter, err = t.batch.NewIter(nil)if err != nil {return nil, err}} else if t.snapshot != nil {iter, err = t.snapshot.NewIter(nil)if err != nil {return nil, err}} else {return nil, ErrDiscardedTransaction}return &iterator{iter: iter}, nil
}

pebble常用方法

NewSnapshot方法

NewSnapshot 方法,用于在 DB 类型上创建一个数据库的快照。
这个方法会返回一个 Snapshot 类型的对象,该对象代表了当前数据库状态的一个点时视图。

NewIndexedBatch 方法

NewIndexedBatch 方法,用于在 DB 类型上创建一个新的读写批处理对象。

参考

[视频、推荐]数据存储与检索(详解b+树存储引擎(innodb、boltdb、buntdb等)、lsm树存储引擎(bitcask、moss、pebble、leveldb等))
参考URL: https://www.bilibili.com/video/BV1Zv411G7ty/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/29652.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

USB 端点停止

文章目录 功能停止USB 设备设置停止特性设备设置端点停止特性示例bRequestwValuewIndex示例USB 主机设置停止特性协议停止握手包中有一个 STALL 包,由 USB 设备方发出,用来表示某个端点不能发送或者接收数据,或者表示不支持控制传输的某种请求。 端点一旦发出 STALL 包,表…

【网络安全】网络安全基础精讲 - 网络安全入门第一篇

目录 一、网络安全基础 1.1网络安全定义 1.2网络系统安全 1.3网络信息安全 1.4网络安全的威胁 1.5网络安全的特征 二、入侵方式 2.1黑客 2.1.1黑客入侵方式 2.1.2系统的威胁 2.2 IP欺骗 2.2.1 TCP等IP欺骗 2.2.2 IP欺骗可行的原因 2.3 Sniffer探测 2.4端口扫描技术…

2024新版AI创作系统pro搭建,支持文生漫画视频ai对话问答/ai音乐创作/ai测评/ai换脸/ai写真

一、系统介绍 一款结合了多种功能应用,是当前市场最热门的AI工具综合体 AI动漫生成 AI音乐创作 AI写真 AI换脸 AI绘画 AI趣测 六大AI功能 AI创作小程序是一种利用人工智能技术为用户提供服务,并通过某种方式实现的小程序。这种小程序可以应用于多…

gRPC(Google Remote Procedure Call Protocol)谷歌远程过程调用协议

文章目录 1、gRPC简介2、gRPC核心的设计思路3、gPRC与protobuf关系 1、gRPC简介 gPRC是由google开源的一个高性能的RPC框架。Stubby Google内部的RPC,演化而来的,2015年正式开源。云原生时代是一个RPC标准。 2、gRPC核心的设计思路 网络通信 ---> gPR…

vue中通过自定义指令实现一个可拖拽,缩放的弹窗

效果 功能描述 按住头部可拖拽鼠标放到边框,可缩放多层重叠丰富的插槽,易于扩展 示例 指令代码 export const dragDialog {inserted: function (el, { value, minWidth 400, minHeight 200 }) {// 让弹窗居中let dialogHeight el.clientHeight ?…

Flink Kafka获取数据写入到MongoDB中 样例

简述 Apache Flink 是一个流处理和批处理的开源框架,它允许从各种数据源(如 Kafka)读取数据,处理数据,然后将数据写入到不同的目标系统(如 MongoDB)。以下是一个简化的流程,描述如何…

Vue61-消息订阅与发布-任意组件之间的通信

一、原理图 原生的JS不能实现订阅与发布,要借助第三方库:pubsub-js(任何一个框架都能用!) 二、案例实现 school组件,需要数据(订阅消息),student组件提供数据&#xff0…

Linux中的EINTR和EAGAIN错误码

Linux中的EINTR和EAGAIN错误码 在Linux系统中,进行系统调用时经常会遇到各种错误码。其中,EINTR(Interrupted system call)和EAGAIN(Resource temporarily unavailable)是两个较为常见的错误码&#xff0c…

MySQL 高级 - 第十二章 | 数据库的设计规范

目录 第十二章 数据库的设计规范12.1 为什么需要数据库设计12.2 范式12.2.1 范式简介12.2.2 范式都包括哪些12.2.3 键和相关属性的概念12.2.4 第一范式(1st NF)12.2.5 第二范式(2nd NF)12.2.6 第三范式(3rd NF&#xf…

JWT详解、JWTUtil工具类的构建方法

一、前言 使用一些用户不友好的项目时,会发现,每一次进入网站,我们都要重新登录。 这是为什么呢? 现代多采用前后端分离的项目架构,这种架构,前后端使用不同的服务器,两个服务器上存储的信息不…

onnx进阶算子优化

一、定义 如何保证pytorch 模型顺利转为onnx. 前言pytorch 算子是如何与onnx 算子对齐的?Asinh 算子出现于第 9 个 ONNX 算子集。PyTorch 在 9 号版本的符号表文件中是怎样支持这个算子的?BitShift 算子出现于第11个 ONNX 算子集。PyTorch 在 11 号版本…

事务AOP

事物管理 事务管理是指对一系列数据库操作进行管理,确保这些操作要么全部成功执行,要么在遇到错误时全部回滚,以维护数据的一致性和完整性。在多用户并发操作和大数据处理的现代软件开发领域中,事务管理已成为确保数据一致性和完…

链表相对于数组的优势,以及栈和队列的基本操作

链表(Linked List)和数组(Array)是两种常见的数据结构,它们各自在不同的场景下有其优势和劣势。链表相对于数组的优势主要体现在以下几个方面: 动态大小: 链表在插入和删除元素时,不…

4M-21:霸气侧漏高效的20+多模态AI模型

大模型技术论文不断,每个月总会新增上千篇。本专栏精选论文重点解读,主题还是围绕着行业实践和工程量产。若在某个环节出现卡点,可以回到大模型必备腔调或者LLM背后的基础模型重新阅读。而最新科技(Mamba,xLSTM,KAN)则…

软件设计不是CRUD(22):在流式数据处理系统中进行业务抽象落地——设计思考

(接上文《软件设计不是CRUD(21):在流式数据处理系统中进行业务抽象落地——需求分析》) 那么思考到这里我们就能做一些关于设计思路的总结: 每一个独立的数据处理流,就是数据采集系统中的一个功能。这个功能具备一个静态的控制逻辑(当然控制逻辑也可以是动态的,本文不…

嵌入式技术学习——c51单片机——蜂鸣器

一、蜂鸣器介绍 蜂鸣器时一种将电信号转化成声音信号的器件,常用来产生设备的按键音,报警音等提示信号。 蜂鸣器分为有源蜂鸣器,无源蜂鸣器 。 有源蜂鸣器:内部自带震荡源,将正负极街上直流电压即可持续发声&#x…

通过摄像头检测步频

通过摄像头识别运动频率,比如步频。 打开摄像头 循环读取视频帧 灰度转换 统计中间一行数值和 人在摄像头前运动,该数值会呈现周期变化 通过快速傅里叶转换,将和步频相似频率显示出来。 (尝试人脸检测,跟着人脸位置变…

深度学习(十)——神经网络:非线性激活

一、Padding Layers简介 nn.ZeroPad2d:在输入的tensor数据类型周围用0进行填充 nn.ConstantPad2d:在输入的tensor数据类型周围用常数进行填充 这个函数的主要作用是对输入的图像进行填充,但里面所有功能都能用nn.Conv2d实现。 二、Non-li…

一文读懂OpenGVLab带来的最新视觉预训练框架

大模型技术论文不断,每个月总会新增上千篇。本专栏精选论文重点解读,主题还是围绕着行业实践和工程量产。若在某个环节出现卡点,可以回到大模型必备腔调或者LLM背后的基础模型重新阅读。而最新科技(Mamba,xLSTM,KAN)则…

为什么直接用 cv2.imwrite 保存 PIL 的图片会导致奇怪的颜色?

在处理图像保存时,使用不同的库可能会导致颜色显示上的差异。特别是 Image.fromarray(synthesis).save 和 cv2.imwrite(save_dir, image) 两种方法之间的区别,会导致保存的图像颜色不同。这篇博客将解释这些方法的区别,以及具体导致颜色差异的…