数据读写流程

news/2024/10/5 13:20:49

数据读写流程

在bitcast论文中,想要获取内存中存储的数据,我们首先得获取索引数据,在索引数据中获取到文件id以及数据存储所在位置,然后根据这些信息去读取文件内容。
所有我们在进行写数据时也得有两步,第一步将key value信息持久化到文件中,第二部是将索引信息保存到内存中。
流程如下图所示
image

数据结构

根据bitcast论文,我们定义一下所需的数据结构信息,option中写入了一些系统的配置信息,例如数据库文件存储位置以及单文数据库文件存储大小等等。

// Db bitcask实例 面向用户的接口
type Db struct {// 系统配置option option// 锁lock *sync.RWMutex// 活动文件activeFile *data.FileData// 老文件列表 只允许读 不允许写oldFile map[uint32]*data.FileData// 内存中存储的索引信息index index.Indexer
}
type option struct {// 文件存储目录DirPath string// 单数据文件大小阈值FileDataSize int64
}

Put

put的业务逻辑和上面的流程图一样先构建logRecord,然后序列化并追加到硬盘中,最后将索引数据

// Put 添加kv
func (db *Db) Put(key []byte, value []byte) error {// 判断key是否合法if len(key) == 0 {return errors.New("key为空")}// 构建logRecordlogRecord := &data.LogRecord{Key:   key,Value: value,Type:  data.Normal,}// 向文件追加数据logRecordPos, err := db.appendLogRecord(logRecord)if err != nil {return errors.New("文件追加失败")}// 将追加的索引添加内存中db.index.Put(key, logRecordPos)return nil
}

在我们的数据文件大小有个阈值,如果阈值超过指定大小阈值则将文件转换成旧的文件并新建一个活动文件进行读写,旧的文件只运行读不允许写。之后将数据序列化并追加到活动文件中,追加完成后将当前数据索引信息进行返回以便于

// 将KV数据追加到文件中
func (db *Db) appendLogRecord(logRecord *data.LogRecord) (*data.LogRecordPos, error) {db.lock.Lock()defer db.lock.Unlock()// 如果当前活跃文件为空 则创建当前活跃文件if db.activeFile == nil {if err := db.setActiveFile(); err != nil {return nil, err}}// 判断文件是否到达阈值 如果到达阈值则将旧的数据文件归档,创建新的数据文件if db.activeFile.WriteOffset >= db.option.FileDataSize {db.oldFile[db.activeFile.FileId] = db.activeFileif err := db.setActiveFile(); err != nil {return nil, err}}// 将记录对象序列化为二进制字节数组encodingData, _ := data.EncodingLogRecord(logRecord)offset := db.activeFile.WriteOffset// 写入到文件中err := db.activeFile.Write(encodingData)if err != nil {return nil, err}return &data.LogRecordPos{FileId: db.activeFile.FileId,Pos:    offset,}, nil
}

整个数据分为数据头和数据体,如下图所示:
image
首先先构建数据头,数据头分为四部分

  • crc: 用于校验数据完整性,这个需要将除crc外的数据对象都构建出来才能进行设置。
  • type: 表示数据是否被删除,如果是删除状态的话则会在合并流程将该值移除调。
  • keySize: key大小
  • valueSize: value大小
    根据key value构建数据头之后,根据字节数构建数据体,最后计算crc校验和后进行返回。
// EncodingLogRecord 将record对象实例化为字节数组并返回长度以及序列化后的对象结果
func EncodingLogRecord(logRecord *LogRecord) ([]byte, int64) {header := make([]byte, 15)// 前3个字节为crc冗余校验位,该位等整个LogRecord读取出来才能进行计算,所以需要先跳过前三个字节,从第四个字节开始设置var index = 4header[index] = logRecord.Typeindex++keySize := len(logRecord.Key)valueSize := len(logRecord.Value)// 写入字节数值到header中 PutVarint会返回每次写入字节数 因为keySize和valueSize不是定长的,所以需要这样设置一些index += binary.PutVarint(header[index:], int64(keySize))index += binary.PutVarint(header[index:], int64(valueSize))// 计算logRecord长度 header长度 + key长度 + value长度var size = int64(index + keySize + valueSize)logRecordByteArray := make([]byte, size)// 将header数据拷贝到logRecordByteArray中copy(logRecordByteArray[:index], header[:index])// 将key value设置到字节数组中 因为key value存储的就是字节数组所以不需要编解码 直接设置即可copy(logRecordByteArray[index:], logRecord.Key)copy(logRecordByteArray[index+keySize:], logRecord.Value)// crc校验和crcResult := crc32.ChecksumIEEE(logRecordByteArray[4:])binary.LittleEndian.PutUint32(logRecordByteArray[:4], crcResult)return logRecordByteArray, size
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

第二章节C代码RUST实现

第二章节书中代码有如下内容这些C语言代码大致实现了一个简单版的 who 命令。这个命令的功能是读取系统的 utmp 文件,并显示当前登录的用户信息。utmp 文件包含关于用户登录会话的信息,包括用户名、登录终端、登录时间等。以下是对上述所有代码实现功能的总结:cp1:实现复制文…

markdown图片管理教程

markdown图片管理教程 由于markdown对图片的支持不够友好,当文件分享给他人的时候经常会出现无法查看图片的情况,而且在博文上传到线上的时候也会出现无法访问图片的情况,因此需要将网上的图片下载到本地,之后再上传到博文中。 本文将会使用vscode的插件来帮助实现所需要的…

python爬虫获取百度热搜

注:本篇学习需要python基础 前言:在上篇中,我们学习了怎么用python发送网页请求来获取网站的源代码,在这篇中,我们将进一步学习 本篇目标:利用python爬虫获取百度热搜 第一步,用浏览器打开百度热搜网站 百度热搜网址 https://top.baidu.com/board?tab=realtime 页面如下…

CC2500和CC1101移植说明

CC1101,CC2500,CC1101模块,CC2500模块,移植说明主要通过如何移植、移植注意、关于芯片配置、如何生成导出配置四大步骤来说明CC2500和CC1101移植首先通过下图1这个宏进行选择 & 如何移植要移植的部分在 CC2500_hal.c 和 CC2500_hal.h中, 搜索 "//移植" 就可以定…

MyBatis的逆向工程详细步骤操作

1. MyBatis的逆向工程详细步骤操作 @目录1. MyBatis的逆向工程详细步骤操作2. 逆向工程配置与生成2.1 MyBatis3Simple:基础版,只有基本的增删改查2.1.1 第一步:在pom.xml 中添加逆向工程插件2.1.2 第二步:配置 generatorConfig.xml2.1.3 第三步:运行插件2.1.4 第四步:测试…

Vue微前端架构与Qiankun实践理论指南

这篇文章介绍了微前端架构概念,聚焦于如何在Vue.js项目中应用Qiankun框架实现模块化和组件化,以达到高效开发和维护的目的。讨论了Qiankun的原理、如何设置主应用与子应用的通信,以及如何解决跨域问题和优化集成过程,从而实现前端应用的灵活扩展与组织。title: Vue微前端架…

中小学电子教材课本下载(简单无脑)

前言 还记得读初中的时候,老是需要借高年级的课本,很是不方便,想要暑假提前预习一下也没资源。现在时代不同了,实用电子课本应该要方便一点。我去看过各类教材的官方网址,大部分电子教材只能在线阅读,不能下载,因此做了一个下载网页,可以直接下载。 简介 人教版电子教材…

Mac 修改默认 shell

Mac 修改默认 shell Mac 自 macOS Catalina 开始默认 shell 由原来的 Bash 改为 zsh 查看 Mac OS 系统版本: https://support.apple.com/zh-cn/109033 查看系统自带所有 shell $ cat /etc/shells # List of acceptable shells for chpass(1). # Ftpd will not allow users to c…