[Golang]K-V存储引擎的学习 从零实现 (RoseDB mini版本)

文章目录

  • 项目的简单介绍
    • 详情
  • 代码分析
    • 项目结构
    • db.go
    • db_file.go
    • entry.go

项目的简单介绍

mini-bitcask的学习,从零实现一个k-v存储引擎
原项目的github地址,感谢Rose大佬
mini-bitcaskrosedbmini版本,博主借此了解k-v存储,该项目通过对一个数据文件进行读写以进行简单示意,而非rosedb多个数据文件的机制,这里也提供rosedb的github地址

详情

此处为rose大佬提供的项目的相关知识的介绍,可供查阅

简而言之的话,minidb设计了数据在内存、磁盘二者中的存放,使用类似LSM的存储结构。
实现了数据PUT、GET、DELETE的功能
核心思想为利用顺序IO来提升性能。

代码分析

这里博主为了学习,由于原main.go固定流程,将其改为可自定义的流程,这里附学习项目的github地址,只对main.go进行了修改,并将数据文件的地址改到项目根目录中。

项目结构

.
├── db_file.go
├── db.go
├── db_test.go
├── entry.go
├── errors.go
├── example
│   └── main.go
├── go.mod
├── minidb.iml
└── README.md

接下来对主要部分进行注释和分析
db_file.go

db.go

定义了MiniBitcask结构体,index使用map在内存中进行key-value的存储,dbfile和dirpath是数据文件的相关信息,mu则用来进行并发的保护

type MiniBitcask struct {indexes map[string]int64 // 内存中的索引信息dbFile  *DBFile          // 数据文件dirPath string           // 数据目录mu      sync.RWMutex
}

db.go主要功能为提供数据库的集成功能创建数据库实例OPEN

实现方法写入数据PUT、取出数据GET、删除数据DEL、合并数据文件merge、关闭db实例CLOSE,也是我们主要使用的功能

实现过程从内存中获取索引exist从数据文件加载索引loadIndexesFromFile

这一部分在原文和源文件中就有代码的分析,这里不再赘述

db_file.go

该部分有关数据文件定义
DBFile结构体包括对应数据文件的句柄,以及下次写入的偏移量、

// DBFile 数据文件定义
type DBFile struct {File          *os.FileOffset        int64HeaderBufPool *sync.Pool
}

newInternal函数创建一个DBFile实例NewDBFile创建一个新的数据文件NewMergeDBFile新建一个合并时的数据文件

func newInternal(fileName string) (*DBFile, error) {// 打开文件,如果不存在则创建file, err := os.OpenFile(fileName, os.O_CREATE|os.O_RDWR, 0644)if err != nil {return nil, err}// 获取文件的状态信息,这里目的是为了获取文件的大小,以设置偏移量offsetstat, err := os.Stat(fileName)if err != nil {return nil, err}// 创建一个对象池,用于存储 Entry 头部数据的缓冲区pool := &sync.Pool{New: func() interface{} {return make([]byte, entryHeaderSize)}}// 返回一个新的 DBFile 对象,其中包括文件的偏移量、打开的文件句柄和对象池return &DBFile{Offset: stat.Size(), File: file, HeaderBufPool: pool}, nil
}

DBFile实现以下方法,Read读取数据Write写入Entry

// Read 从 offset 处开始读取,在引擎初始化时,这里被循环调用
func (df *DBFile) Read(offset int64) (e *Entry, err error) {// 从对象池中获取一个用于存储数据的缓冲区buf := df.HeaderBufPool.Get().([]byte)defer df.HeaderBufPool.Put(buf) // 确保在函数返回时将缓冲区归还给对象池// 从文件中读取数据到缓冲区if _, err = df.File.ReadAt(buf, offset); err != nil {return}// 解码缓冲区中的数据为 Entry 对象if e, err = Decode(buf); err != nil {return}// 计算键和值在文件中的偏移量,并读取键和值的数据offset += entryHeaderSize // 将偏移量移到键值对数据开始的位置// 如果键的大小大于 0,则读取键的数据if e.KeySize > 0 {key := make([]byte, e.KeySize) // 创建一个存储键数据的切片if _, err = df.File.ReadAt(key, offset); err != nil {return}e.Key = key // 将读取的键数据赋值给 Entry 对象}// 更新偏移量,准备读取值的数据offset += int64(e.KeySize) // 将偏移量移到值数据开始的位置// 如果值的大小大于 0,则读取值的数据if e.ValueSize > 0 {value := make([]byte, e.ValueSize) // 创建一个存储值数据的切片if _, err = df.File.ReadAt(value, offset); err != nil {return}e.Value = value // 将读取的值数据赋值给 Entry 对象}// 返回读取的 Entry 对象及可能的错误return
}

write方法的实现可以参考read

entry.go

Entry定义这里的一条记录,该包即为如何包装一条记录
一条entry包括key、value的值和大小标志位mark

// Entry 写入文件的记录
type Entry struct {Key       []byteValue     []byteKeySize   uint32ValueSize uint32Mark      uint16
}

NewEntry根据传入的参数返回一条Entry实例
并实现了Entry的编码Encode解码Decode 方法
encode定义了entry编码的顺序,decode可以参考这部分

// Encode 编码 Entry,返回字节数组
func (e *Entry) Encode() ([]byte, error) {buf := make([]byte, e.GetSize())binary.BigEndian.PutUint32(buf[0:4], e.KeySize)binary.BigEndian.PutUint32(buf[4:8], e.ValueSize)binary.BigEndian.PutUint16(buf[8:10], e.Mark)copy(buf[entryHeaderSize:entryHeaderSize+e.KeySize], e.Key)copy(buf[entryHeaderSize+e.KeySize:], e.Value)return buf, nil
}

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

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

相关文章

2024年腾讯云免费服务器4核8G配置申请

腾讯云免费服务器4核8G配置申请入口 https://curl.qcloud.com/FJhqoVDP 免费服务器可选轻量应用服务器和云服务器CVM,轻量配置可选2核2G3M、2核8G7M和4核8G12M,CVM云服务器可选2核2G3M和2核4G3M配置,腾讯云服务器网txyfwq.com分享2024年最新腾…

如何在webapp中手动部署

前言:这个有不知道怎么下载Tomcat的可以看我这篇博客的前面,有相关链接,下载好后我那边也有如何运行成功的 在idea中配置tomcat服务器,部署一个项目-CSDN博客 接下来进入这篇博客的正题!怎么手动部署 先找到我们下载…

【业务功能篇145】Spring项目中线程池实战应用各种场景ThreadPoolTaskExecutor

【业务功能篇 142】多线程池Semaphore信号量 数据并行处理-CSDN博客 【业务功能篇135】多线程countDownLatch执行大数据量定时任务_countdownlantch 实现多个线程开始执行任务的最大并行性-CSDN博客 线程池ThreadPoolTaskExecutor实战-CSDN博客 springboot线程池ThreadPoo…

每日GEE| Day 01 研究区域矢量数据加载

// Add study region var roi ee.FeatureCollection(geometry) Map.centerObject(roi,8); var styling {color:red,fillColor:00000000,width:2};// display hollow roi Map.addLayer(roi.style(styling), {}, "outline"); 以上代码的功能实现了对研究区域的加载&am…

C语言如何初始化⼆维数组?

一、问题 ⼆维数组怎样初始化,有⼏种⽅法? 二、解答 ⼆维数组和⼀维数组⼀样,也可以在声明时对其进⾏初始化。⼆维数组的初始化⽅式⽐⼀维数组较为复杂,但都是由⼀维数组初始化⽅法⾏⽣⽽来的。在给⼆维数组赋初值时,…

Java零基础入门-如何代码模拟斗地主洗牌发牌动作(上)?

一、本期教学目标 掌握map集合常用方法。掌握map集合使用场景。通过map集合实现斗地主洗牌发牌动作。 二、前言 对于双列集合之map集合,它的相关知识点及拓展咱们都已经差不多学完了。接下来,就是带着大家如何灵活运用map进行一个实战教学,…

阿联酋将资助 OpenAI 的内部芯片

据《金融时报》报道,OpenAI计划开发自己的半导体芯片,以支持高级AI模型的野心可能会从阿拉伯联合酋长国(UAE)获得支持。 报道称,阿布扎比的国家支持集团MGX正在讨论支持OpenAI的内部构建AI芯片的计划。这一信息来自于…

FFmpeg-aac、h264封装flv及时间转换

文章目录 时间概念流程api核心代码 时间概念 dts: 解码时间戳, 表示压缩帧的解码时间 pts: 显示时间戳, 表示将压缩帧解码后得到的原始帧的显示时间 时间基: time_base , 通常以ms为单位 时间戳: timestamp , 多少个时间基 真实时间:time_base * timest…

如何设计高并发系统

1.局部并发原则 复杂的业务,把不相关的用异步执行,这样的话有几个问题:1.第一个一步失败了,本来不用执行后面的逻辑,现在改成异步,无法 控制,增加数据库的压力。性能本来就是资源换时间嘛&#…

力扣111---二叉树的最小深度(简单题,Java,递归+非递归)

目录 题目描述: (递归)代码: (非递归、层次遍历)代码: 题目描述: 给定一个二叉树,找出其最小深度。 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。 说…

ping和telnet的区别

ping是ICMP协议,只包含控制信息没有端口,用于测试两个网络主机之间网络是否畅通 telnet是TCP协议,用于查看目标主机某个端口是否开发。 总结:ping是物理计算机间的网络互通检查,telnet是应用服务间的访问连通检查&am…

Windows XP 部署 高版本的VisualStudio运行库

由于缺少对 SHA-256 代码签名证书的支持,适用于 Visual Studio 2015、2017、2019 和 2022 的最新 Visual C 可再发行程序包中不再提供对 Windows XP 的运行时库支持。 Visual Studio 2019 版本 16.7 中随附有支持 Windows XP 的最后一个可再发行程序包。 请使用文件…

Android中ANR机制

Android中的ANR分为两种,前台ANR和后台ANR。 前台ANR,是指ANR时对用户可感知,比如拥有当前前台可见的activity的进程,或者拥有前台通知的fg-service的进程,这些是用户可感知的场景。前台ANR,会出现一个系统…

vue模板语法介绍及内置指令用法

1、文本差值(大括号、v-text、v-htm指令) 最基本的数据绑定就是文本差值,格式为“Mustache”语法(双大括号); 双大括号只能解析文本不能解析html,如需解析html则需使用v-html指令;…

C语言之通讯录的实现(静态版,动态版,文件版)

个人主页(找往期文章包括但不限于本期文章中不懂的知识点): 我要学编程(ಥ_ಥ)-CSDN博客 目录 静态通讯录的实现逻辑 test.c:通讯录的逻辑实现 Contact.h:函数的声明与头文件的包含 Contact.c:函数的…

MySQL数据库实现增删改查基础操作

准备工作 安装mysql8.0 (安装时一定要记住用户名和密码)安装数据库可视化视图工具Navicat 请注意⚠️⚠️⚠️⚠️ a. 编程类所有软件不要安装在中文目录下 b. Navicat破解版下载安装教程:(由于文章审核提示版权问题,链接不方便给出&#xff…

Spring Web MVC入门(3)

学习Spring MVC 请求 传递JSON数据 JSON概念 JSON: JavaScript Object Natation JSON是一种轻量的数据交互格式, 采用完全独立于编程语言的文本格式来存储和标识数据. 简单来说, JSON是一种数据格式, 有自己的格式和语法, 使用文本来表示对象或数组的信息, 因此JSON的本质…

C++——类和对象(3)

目录 1. 拷贝构造 1.1 概念 1.2 特性 ​编辑 2. 赋值重载 和 运算符重载 2.1 运算符重载 2.2 赋值重载 此篇文章讲解六个默认成员函数中的 拷贝构造和赋值重载 。 1. 拷贝构造 1.1 概念 拷贝构造: 在创建对象的时候用已经创建好的对象去初始化一个新对象&am…

C# 打开文件对话框(OpenFileDialog)

OpenFileDialog&#xff1a;可以打开指定后缀名的文件&#xff0c;既能单个打开文件也能批量打开文件 /// <summary>/// 批量打开文档/// 引用&#xff1a;System.Window.Fomrs.OpenFileDialog/// </summary>public void OpenFile(){OpenFileDialog dialog new Op…

操作系统(OS)

文章目录 前言一、操作系统是什么&#xff1f;二、用户对资源的访问三、操作系统是怎么做到管理的&#xff1f; 前言 任何计算机系统都包含一个基本的程序集合&#xff0c;称为操作系统(OS)。冯诺依曼体系结构中的硬件单元提供的功能&#xff0c;这些硬件由操作系统来控制与管…