继续继续...

转眼都开学啦...


Building Blocks 2

building blocks里讲了一些关于Log structure storage的东西,这也是用于在硬盘上持久化KvStore要用的结构。我们边做project边看吧


Project 2

这次要Create a persistent key/value store that can be accessed from the command line,意思就是要写硬盘啦。我们给project2起个名字吧:KVS2.0

Bitcask

我们会使用Building Blocks 2中讲过的Bitcask,这是一种日志型key-value存储模型。Bitcask的核心思想就是把key对应的具体的值存到硬盘上,在写内存的同时维护一个硬盘上的log file(类似RocksDB中的WAL),这样就可以把数据持久化啦。

ref: https://cloud.tencent.com/developer/article/1083737

https://blog.csdn.net/chdhust/article/details/77801890

根据Bitcask的思想,那我们的KVS2.0就这样设计:

KVS2.0要支持以下几种操作(和之前的project1差不多):

  • Set <KEY> <VALUE>

    • 对于不存在的新记录,向log file中存record(注意维护idx++),并在index中存储<key, idx>
    • 对于已存在的新纪录,向log file中存record(还是idx++,旧的先不动),并在index中更新<key, idx>
    • 一个写操作需要进行 一次顺序的磁盘写入 和 一次内存操作。
  • Get <KEY>

    • 先在idex中key对应的idx,然后在log file中找idx对应的value,返回
  • Rm <KEY>

    • 删掉index中的<key, idx>键值对。Log file不动
  • Replay

    • 刚重启程序时index是空的,需要根据log file重建内存中的index
  • compaction:删除log file中无用的块

    • 定期将所有older data file中的数据扫描一遍并生成新的data file(没有包括active data file 是因为它还在不停写入),这里的merge其实就是将对同一个key的多个操作以只保留最新一个的原则进行删除。

另外Bitcask还支持一些特性,但现在我们暂(tou)时(lan)先不实现啦:

  • 当一个log file过大时,另外建立一个新的log file
  • Hint file

Error handeling in rust

因为磁盘io是可能存在错误的(比如硬盘被人跺了一脚),所以这次我们还要考虑rust中的error handeling

Rust工程的文件结构

project 2和project 1的文件结构很像,唯一不同点就是多了一个error.rs,用于错误处理。

刚上来写好像有种无从下手的感觉....我们不妨先分析一下Brain大神的样例。

BufReader和BufWriter

首先来看最核心的KvStore的结构。它被定义在kv.rs中。之前我们提到要记录log file,假设我们就用一个简单的文本文件作为log(用别的格式比如json也可以,反正原理是一样的),那么它的格式应该是这样的:

idx "key":"val"

比如
"qq": "mahuateng"
"zzz": "qaqaqaq"
"llc": "nbnbnbnbnbnb"
"hfut": "nb666"

其中idx是一个递增的计数器。那么如果我们要在rust中做到能随时定位这个文本文件中的每一行(即每个record),就需要如下信息:

该行在文件中的起始位置
该行在文件中的结束位置
该行记录的长度
该行记录的idx

Rust提供了std::io,这是一个进行io操作的库。为了方便进行文件读写操作,可以定义 BufReaderWithPos 和 BufWriterWithPos 两个结构体:

struct BufReaderWithPos<R: Read + Seek> {     //BufReaderWithPos可以同时作用在Read和Seek两种trait上
reader: BufReader<R>, //读缓冲区
pos: u64, //当前读位置的指针
}
BufReaderWithPos实现了read和seek函数。
new时会用给定的文件(File)初始化BufReader。seek时将文件定位到指定的位置。 struct BufWriterWithPos<W: Write + Seek> { //BufWriterWithPos可以同时作用在Write和Seek两种trait上
writer: BufWriter<W>, //写缓冲区
pos: u64, //当前写位置的指针
}
BufReaderWithPos实现了write,seek,flush函数。
new时会用给定的文件(File)初始化BufWriter。

这样我们就有了对文件进行读写的工具。

KvStore

接下来看最主要的struct:KvStore。里面的成员变量如下:

pub struct KvStore {
// directory for the log and other data
path: PathBuf, // map generation number to the file reader
// 一条记录的idx->它在log file中的位置,用于读记录
readers: HashMap<u64, BufReaderWithPos<File>>, // writer of the current log
// 用于写记录
writer: BufWriterWithPos<File>, current_gen: u64, //
index: BTreeMap<String, CommandPos>, // the number of bytes representing "stale" commands that could be deleted during a compaction
uncompacted: u64,
}

这里我们重点关注这两个HashMap。

1

Rust学习笔记2的更多相关文章

  1. Rust学习笔记1

    这是一份不错的rust教程,目前包括4个block和4个project.全部完成后可以用rust实现一个简单的key-value存储引擎. 注意:Windows下rust貌似会遇到一些bug,强烈建议 ...

  2. Rust学习笔记一 数据类型

    写在前面 我也不是什么特别厉害的大牛,学历也很低,只是对一些新语言比较感兴趣,接触过的语言不算多也不算少,大部分也都浅尝辄止,所以理解上可能会有一些偏差. 自学了Java.Kotlin.Python. ...

  3. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  4. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  5. PHP-会员登录与注册例子解析-学习笔记

    1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...

  6. 2014年暑假c#学习笔记目录

    2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...

  7. JAVA GUI编程学习笔记目录

    2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...

  8. seaJs学习笔记2 – seaJs组建库的使用

    原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最 ...

  9. CSS学习笔记

    CSS学习笔记 2016年12月15日整理 CSS基础 Chapter1 在console输入escape("宋体") ENTER 就会出现unicode编码 显示"%u ...

随机推荐

  1. mysql AVG()函数 语法

    mysql AVG()函数 语法 作用:AVG 函数返回数值列的平均值.NULL 值不包括在计算中.大理石模组 语法:SELECT AVG(column_name) FROM table_name m ...

  2. Codeforces 960F Pathwalks ( LIS && 树状数组 )

    题意 : 给出若干个边,每条边按照给出的顺序编号,问你找到一条最长的边权以及边的编号同时严格升序的一条路径,要使得这条路径包含的边尽可能多,最后输出边的条数 分析 :  这题和 LIS 很相似,不同的 ...

  3. Anaconda是如何进行版本管理的?

    创建不同的environments,在电脑中会有不同的文件夹 然后,当使用conda下载时,会下载到不同的env文件夹下(提前进行env切换) 那么不是在anaconda prompt命令行下下载的呢 ...

  4. 【转载】Save terminal output to a file

    To write the output of a command to a file, there are basically 10 commonly used ways. Overview: Ple ...

  5. splice()、slice()、split()函数的区分

    1.slice(数组) 用法:array.slice(start,end) 解释:该方法是对数组进行部分截取,并返回一个数组副本:参数start是截取的开始数组索引,end参数等于你要取的最后一个字符 ...

  6. 原型模式故事链(4)--JS执行上下文、变量提升、函数声明

    上一章:JS的数据类型 传送门:https://segmentfault.com/a/11... 好!话不多少,我们就开始吧.对变量提升和函数声明的理解,能让你更清楚容易的理解,为什么你的程序报错了~ ...

  7. JavaScript 文件拖拽上传插件 dropzone.js 介绍

    http://www.renfei.org/blog/dropzone-js-introduction.html

  8. 【机器学习速成宝典】模型篇05朴素贝叶斯【Naive Bayes】(Python版)

    目录 先验概率与后验概率 条件概率公式.全概率公式.贝叶斯公式 什么是朴素贝叶斯(Naive Bayes) 拉普拉斯平滑(Laplace Smoothing) 应用:遇到连续变量怎么办?(多项式分布, ...

  9. 身份证最后一位按照ISO7064:1983.MOD11-2校验码

    居民身份证号码,根据[中华人民共和国国家标准 GB 11643-1999]中有关公民身份号码的规定,公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成.排列顺序从左至右依次为:六位数字地 ...

  10. VLC for Android编译

    编译环境是ubuntu 64bit 全程参考https://wiki.videolan.org/AndroidCompile/ 一:环境准备 1.安装系统 尽量使用最新的ubuntu系统 可以省去很多 ...