GoFly框架中集成Bolt 和badfer两个Go语言嵌入式键值数据库

本插件集成了Bolt 和badfer两个纯Go实现的快速的嵌入式K/V数据库,方便开发时本地存储使用。插件集成Bolt 和badfer两个,如果确定使用其中一个,也可以把其中不用的一个删除,不删除也不会有任何影响。

插件使用说明

1.安装插件

到busines后台的开发者工具下的代码仓找到“​​Go语言嵌入式键值数据库​​​”进行安装即可

2.代码说明

插件安装到utils\plugin目录中,其中在app\business\storage中有两个调用演示文件,一个是kv的字符串形式数据,一个是user用户对象信息json数据。

3.配置说明

在utils\plugin\storage\config\config.go的配置文件有两个参数 ,DataPath是创建的数据库文件存放位置,MetadataStorage是使用Bolt或者是badfer,默认是bolt。

4.如何调用

调用直接 plugin.Storager.函数名 方式。例如:

// 获取桶中数据列表
func (t *Kv) List(offset, limit int) ([][]byte, error) {return plugin.Storager.List(t.key(""), offset, limit)
}// 获取数据
func (t *Kv) Get(key string) ([]byte, error) {return plugin.Storager.Get(t.key(key))
}// 保存数据
func (t *Kv) Set(key string, val []byte) error {return plugin.Storager.Set(t.key(key), val)
}// 删除桶中的key
func (t *Kv) Delete(key string) error {return plugin.Storager.Delete(t.key(key))
}// 删除桶
func (t *Kv) DeleteBucket() error {return plugin.Storager.DeleteBucket(t.key(""))
}
// 设置可以名称
func (t *Kv) key(key string) string {return "kv/" + key
}

其中func (t *Kv) key(key string) string {}是配置key名称字符串。封装是约定传key是把桶和key用/拼接的字符串。调用是接口拿到字符串后解析拿到桶名和key名称。

5.接口调用示例代码

这是安装插件后端再app\business\storage\user.go得到演示代码,在开发时你可以参数使用,完整代码如下:

package storageimport ("encoding/json""gofly/utils/gf""gofly/utils/plugin""time"
)type User struct {NoNeedLogin []string //忽略登录接口配置-忽略全部传[*]NoNeedAuths []string //忽略登录接口配置-忽略全部传[*]
}// 定义用户数据结构体
type UserData struct {ID        string    `json:"_id"`Name      string    `json:"name"`Role      string    `json:"role"`Salt      string    `json:"salt,omitempty"`Password  string    `json:"password,omitempty"`CreatedAt time.Time `json:"created_at"`
}// 初始化路由
func init() {fpath := User{NoNeedLogin: []string{"*"}, NoNeedAuths: []string{"*"}}gf.Register(&fpath, fpath)
}// 创建数据
func (api *User) AddData(c *gf.GinCtx) {param, _ := gf.RequestParam(c)red := api.Set(gf.String(param["id"]), UserData{ID: gf.String(param["id"]), Name: gf.String(param["name"]), Role: gf.String(param["role"]), CreatedAt: time.Now()})gf.Success().SetMsg("创建数据成功").SetData(red).Regin(c)
}// 获取数据
func (api *User) GetData(c *gf.GinCtx) {id := c.DefaultQuery("id", "")if id == "" {gf.Failed().SetMsg("参数id不能为空").Regin(c)return}data, err := api.Get(id)if err != nil {gf.Failed().SetMsg(err.Error()).Regin(c)return}gf.Success().SetMsg("获取数据成功").SetData(data).Regin(c)
}// 删除字段数据
func (api *User) DeleteData(c *gf.GinCtx) {param, _ := gf.RequestParam(c)if _, ok := param["id"]; !ok {gf.Failed().SetMsg("参数id不能为空").Regin(c)return}err := api.Delete(gf.String(param["id"]))if err != nil {gf.Failed().SetMsg(err.Error()).Regin(c)return}gf.Success().SetMsg("删除字段数据成功").Regin(c)
}// 删除桶
func (api *User) DelBucket(c *gf.GinCtx) {err := api.DeleteBucket()if err != nil {gf.Failed().SetMsg(err.Error()).Regin(c)return}gf.Success().SetMsg("删除桶成功").Regin(c)
}// 获取数据列表
func (api *User) GetList(c *gf.GinCtx) {offset := gf.Int(c.DefaultQuery("offset", "0"))pageSize := gf.Int(c.DefaultQuery("pageSize", "10"))list, err := api.List(offset, pageSize)if err != nil {gf.Failed().SetMsg(err.Error()).Regin(c)return}gf.Success().SetMsg("获取数据列表").SetData(list).Regin(c)
}// 操作基础
func (t *User) List(offset, limit int) ([]*UserData, error) {data, err := plugin.Storager.List(t.key(""), offset, limit)if err != nil {return nil, err}users := make([]*UserData, 0, len(data))for _, d := range data {u := new(UserData)err = json.Unmarshal(d, u)if err != nil {return nil, err}users = append(users, u)}return users, nil
}func (t *User) Get(id string) (*UserData, error) {data, err := plugin.Storager.Get(t.key(id))if err != nil {return nil, err}u := new(UserData)err = json.Unmarshal(data, u)return u, err
}func (t *User) Set(id string, val UserData) error {data, err := json.Marshal(val)if err != nil {return err}return plugin.Storager.Set(t.key(id), data)
}// 删除桶中key
func (t *User) Delete(id string) error {return plugin.Storager.Delete(t.key(id))
}// 删除桶
func (t *User) DeleteBucket() error {return plugin.Storager.DeleteBucket(t.key(""))
}// 组装key包含桶名和用户的id
func (t *User) key(id string) string {return "user/" + id
}

BoltDB 介绍

BoltDB 是一个用 Go 语言编写的 嵌入式键值对数据库,基于 LMDB(Lightning Memory-Mapped Database)设计,专注于高性能和简单性。它无需独立服务,直接嵌入到应用程序中,适合单机场景,支持 ACID 事务。

1. 核心特点

  • 键值存储:数据以 ​​[]byte​​ 格式存储,支持嵌套 Bucket(类似命名空间)。
  • 事务性:提供完整的 ACID 事务(读/写隔离),支持并发读,写操作串行化。
  • 零依赖:纯 Go 实现,无需外部服务或依赖库。
  • 内存映射:通过内存映射文件提升读取性能,写入通过 COW(写时复制)保证数据安全。
  • B+树索引:数据按字典序排序,支持范围查询和前缀扫描。

2. 适用场景

  • 小型到中型单机应用(如配置文件、缓存、会话存储)。
  • 需要高可靠性的本地数据持久化(如 IoT 设备、桌面应用)。
  • Go 生态项目快速集成轻量级存储。

BoltDB 是 Go 生态中轻量级、高可靠的嵌入式存储方案,适合需要简单事务和本地持久化的场景,但需权衡其单机写入瓶颈和内存限制。

BadgerDB 介绍

BadgerDB 是一个用 Go 语言编写的高性能键值对数据库,基于 LSM-Tree(Log-Structured Merge-Tree) 设计,专为高吞吐量写入和低延迟读取场景优化。与 BoltDB 不同,BadgerDB 通过混合内存与磁盘存储,支持海量数据的高效存取,同时保持 ACID 事务特性。

1. 核心特点

  • LSM-Tree 架构
  • 写入先写入内存表(MemTable),再异步合并到磁盘(SSTable),适合高吞吐写入。
  • 数据按层级合并(Compaction),自动优化存储结构。
  • 键值分离(可选):
  • 大 Value 单独存储,减少 LSM-Tree 内部碎片,提升查询效率。
  • ACID 事务
  • 支持快照隔离(Snapshot Isolation),保证事务一致性。
  • 低延迟读取
  • 内存缓存热点数据,结合布隆过滤器(Bloom Filter)加速查询。
  • 跨平台:纯 Go 实现,无外部依赖,支持 Linux/macOS/Windows。

2. 适用场景

  • 高频写入场景:日志采集、实时指标存储、时序数据(如 IoT 设备数据)。
  • 大 Value 存储:文档、图片等二进制数据(需开启键值分离)。
  • 高并发读:缓存系统、元数据索引。
  • 替代 LevelDB/RocksDB:需 Go 原生集成且无需 CGO 的场景。

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

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

相关文章

AWS - Redshift - 外部表读取 Parquet 文件中 timestamp 类型的数据

问题: 通过 Redshift Spectrum 功能可以读取 S3 中的文件,当读取 Parquet 文件时,如果列格式设置为 timestamp, 通过 psql 客户端读取会出现以下错误: testdb# select * from myspectrum_schema_0219.test_ns; ERROR…

Pretraining Language Models with Text-Attributed Heterogeneous Graphs

Pretraining Language Models with Text-Attributed Heterogeneous Graphs EMNLP 推荐指数:#paper/⭐⭐#​ 贡献: 我们研究了在更复杂的数据结构上预训练LM的问题,即,TAHG。与大多数只能从每个节点的文本描述中学习的PLM不同&…

重新求职刷题DAY18

1.513. 找树左下角的值 给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。 假设二叉树中至少有一个节点。 示例 1: 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 输入: root [2,1,3] 输出: 1思路: 这…

B站pwn教程笔记-2

这次是栈溢出基础。 栈基础知识 栈帧结构概览 看上图的高地址和低地址。arguments是子函数的形参。蓝色的是上一个栈的ebp值,用于在子函数执行完毕之后,返回到正确的ebp. heap的占的内存大大的超过stack。 下面看看调用栈的详细过程。 一个函数都是以…

Qt中C++与QML交互从原理、方法与实践陷阱深度解析

在我们使用Qt开发中,现在以及普遍通过 C 与 QML 的交互,将 C 的强大功能与 QML 的界面设计优势相结合,既保证了应用程序的性能和稳定性,又能快速实现美观、易用的用户界面。接下来专门讲下C与QML交互原理、方法与实践中的一些陷阱…

JavaScript获取DOM元素语法总结(getElementsByName()、querySelector()、querySelectorAll())

文章目录 JavaScript DOM 元素获取语法总结关键点简介方法概述详细报告引言DOM 元素获取方法1. getElementById()(弃用)2. getElementsByClassName()(弃用)3. getElementsByTagName()(弃用)4. getElementsB…

tableau之人口金字塔、漏斗图、箱线图

一、人口金字塔 人口金字塔在本质上就是成对的条形图 人口金字塔是一种特殊的旋风图 1、数据处理 对异常数据进行处理 2、创建人口金字塔图 将年龄进行分桶 将男女人数数据隔离开 分别绘制两个条形图 双击男性条形图底部,将数据进行翻转(倒序&a…

首次使用WordPress建站的经验分享(一)

之前用过几种内容管理系统(CMS),如:dedeCMS、phpCMS、aspCMS,主要是为了前端独立建站,达到预期的效果,还是需要一定的代码基础的,至少要有HTML、Css、Jquery基础。 据说WordPress 是全球最流行的内容管理系统CMS,从现在开始记录一下使用WordPress 独立建站的步骤 选购…

【Viewer.js】vue3封装图片查看器

效果图 需求 点击图片放大可关闭放大的 图片 下载 cnpm in viewerjs状态管理方法 stores/imgSeeStore.js import { defineStore } from pinia export const imgSeeStore defineStore(imgSeeStore, {state: () > ({showImgSee: false,ImgUrl: ,}),getters: {},actions: {…

人工智能 阿里云算力服务器的使用

获取免费的阿里云服务器 阿里云免费使用地址: https://free.aliyun.com/ 选择 人工智能平台 PAI 选择交互式建模 再选建立实例。 选择对应的GPU 和镜像,点击确认。 注意:250个小时,用的时候开启,不用的时候关闭&…

mysql将表导出为sql文件

使用mysqldump命令 mysqldump是MySQL提供的一个命令行工具,用于导出数据库或表的结构和数据。要将表导出为SQL文件,可以使用以下命令: mysqldump -uroot -p123456 database_name table_name > output_file.sql

用HTML5+CSS+JavaScript实现新奇挂钟动画

用HTML5+CSS+JavaScript实现新奇挂钟动画 引言 在技术博客中,如何吸引粉丝并保持他们的关注?除了干货内容,独特的视觉效果也是关键。今天,我们将通过HTML5、CSS和JavaScript实现一个新奇挂钟动画,并将其嵌入到你的网站中。这个动画不仅能让你的网站脱颖而出,还能展示你的…

大语言模型(LLM)微调技术笔记

图1:大模型进化树2 大模型微调 在预训练后,大模型可以获得解决各种任务的通用能力。然而,越来越多的研究表明,大语言模型的能力可以根据特定目标进一步调整。 这就是微调技术,目前主要有两种微调大模型的方法1&…

AI汽车新风向:「死磕」AI底盘,引爆线控底盘新增长拐点

2025开年,DeepSeek火爆出圈,包括吉利、东风汽车、上汽、广汽、长城、长安、比亚迪等车企相继官宣接入,掀起了“AI定义汽车”浪潮。 而这股最火的AI汽车热潮,除了深度赋能智能座舱、智能驾驶等AI竞争更白热化的细分场景&#xff0…

硬件学习笔记--46 电能表影响量试验梳理

目录 1.电流和电压电路中的谐波影响试验 1)电流和电压电路中谐波——第5次谐波试验 2)电流和电压电路中谐波——方顶波波形试验 3)​​​​​​​电流和电压电路中谐波——尖顶波波形试验 4)​​​​​​​电流和电压电路中谐…

第15天学习:类和对象的概念

我用大白话生活化例子帮你彻底搞懂类和对象!🐶 🌈 1分钟快速理解版 类 设计图纸(比如:手机设计图) 对象 根据图纸造出来的实物(比如:你的iPhone 15和小明的华为P60) …

Linux 命令大全完整版(05)

2. Linux 系统设置命令 export 功能说明:设置或显示环境变量。语  法:export [-fnp][变量名称][变量设置值]补充说明:在 shell 中执行程序时,shell 会提供一组环境变量。export 可新增、修改或删除环境变量,供后续…

deepseek清华大学第二版 如何获取 DeepSeek如何赋能职场应用 PDF文档 电子档(附下载)

deepseek清华大学第二版 DeepSeek如何赋能职场 pdf文件完整版下载 https://pan.baidu.com/s/1aQcNS8UleMldcoH0Jc6C6A?pwd1234 提取码: 1234 或 https://pan.quark.cn/s/3ee62050a2ac

01 冲突域和广播域的划分

目录 1、冲突域和广播域的划分 1.1、冲突域 1.2、广播域 1.3、对比总结 1.4、冲突域与广播域个数计算例题 2、交换机和路由器的结构 2.1、交换机的结构 2.2、路由器的结构 1、冲突域和广播域的划分 1.1、冲突域 冲突域是指网络中可能发生数据帧冲突的物理范围。当多…

vLLM学习1

调用方式 一、vLLM 提供的两种调用方式 1. Offline Batched Inference(离线批处理) 调用特点:一次性传入一批(batch)的请求,等待所有请求都处理完毕后,一次性返回推理结果。对用户而言&#x…