一文彻底搞懂leveldb架构
leveldb
leveldb是一个写性能十分优秀的存储引擎,是典型的LSM-tree的实现。LSM的核心思想是为了换取最大的写性能而放弃掉部分读性能。那么,为什么leveldb写性能高?简单来说它就是尽量减少随机写的次数。leveldb首先将数据更新到内存中。当内存中的数据量达到一定阈值,将这部分数据再真正刷新到磁盘文件中。一般来说,顺序写60MB/s,随机写45MB/s.
整体架构
leveldb主要由以下几个重要的部件构成:
1.memtable
2.immutable memtable
3.sstable
4.manifest
5.current
6.log
memtable
刚才提到leveldb的一次写入操作并不是直接将数据写入到磁盘文件,而是采用先将数据写入内存的方式。所以,memtable就是一个内存中进行数据组织与维护的结构。在memtable中,数据按用户定义的方法排序之后按序存储。等到其存储内容到达阈值时(4MB)时,便将其转换成一个不可修改的memtable,与此同时创建一个新的memtable来供用户进行读写操作。memtable底层采用跳表,它的大多数操作都是O(logn)。
immutable memtable
当memtable的容量达到阈值时,便会转换成一个不可修改的memtable即immutable memtable。它同memtable的结构定义一样。两者的区别只是immutable memtable是只读的。immutable memtable被创建时,leveldb的后台压缩进程便会利用其中的内容创建一个sstable,然后持久化到磁盘中。
sstable
leveldb虽然采用了先写内存的方式来提高写效率。但是内存中的数据不可能是无线增长,并且日志中记录的写入操作过多会造成异常发生,而且恢复时间过长。因此内存中的数据达到一定容量就得将数据持久化到磁盘中。除了某些元数据文件,leveldb的数据主要都是通过sstable来存储的。
虽然在内存中,所有的数据都是按序排列的,但是当多个memtable数据持久化到磁盘后,其对应的sstable之间是存在交集的,这样造成在读操作时得对所有的sstable文件进行遍历,严重影响了读效率。所以,leveldb会定期整合这些文件,也叫做compaction。随着compaction的进行,sstable文件在逻辑上被分成若干层。通过内存数据直接dump出来的是level 0 层文件,后期整合出来的level i层文件。sstable本身是不可修改的。
manifest
在leveldb中有个版本的概念。一个版本记录了每一层所有文件的元数据。元数据包括如下几点:
- 文件大小
- 最大key值
- 自小key值
版本信息十分关键,除了在查找数据时利用两个key值来加快查找,还在其中为了一些compaction的统计值来控制compaction的进行。
可以看到文件的元数据主要包含最小和最小key
// tFile holds basic information about a table.
type tFile struct {fd storage.FileDescseekLeft int32size int64imin, imax internalKey
}
版本则维护了每一层所有文件的元数据信息。入下代码所示:
type version struct {s *session // session - versionlevels []tFiles // file meta// Level that should be compacted next and its compaction score.// Score < 1 means compaction is not strictly needed. These fields// are initialized by computeCompaction()cLevel int // next levelcScore float64 // current scorecSeek unsafe.Pointerclosing boolref intreleased bool
}
当每次compaction完成时,leveldb都会创建一个新的version。compaction完成简单来说就是sstable的新增或者减少。而version创建的规则是:
versionNew = versionOld + versionEdit
这里的versionEdit指的是在旧版本基础上变化的内容。一般指sstable的增加或者删除。
manifest文件就是用来记录这些versionEdit信息的。一个versionEdit数据会编码成一条记录写入到manifest文件中。如下图所示
一共有两条versionEdit记录,每条记录包括
- 新增哪些sstable文件
- 日志文件编号
- 删除哪些sstable文件
- 当前compaction的下标
- 操作seqNumber等信息
通过这些信息,leveldb变可以启动时创建一个空的version,不断apply这些记录。最终可以得到一个上次运行结束时的版本信息。
current
主要是记录当前manifest 的文件名。为什么需要这个?因为leveldb每次启动时,都会创建一个新的manifest文件,因此会出现很多个manifest文件。current则用来指出那个才是我们需要关心的文件。
log
leveldb写操作不是直接写入磁盘,而是先写入内存。加入写入到内存的数据还未来得及持久化,leveldb发生异常或者服务器宕机等会造成写入的数据丢失。因此,leveldb在写入内存之前会首先将所有的写操作写入日志文件中。每次写操作都是一次顺序写入,这样写效率高,整体写入性能好。此外,leveldb写操作的原子性也可以通过log来实现。
异常情况主要有以下几种:
1.写log完成,写内存未完成
2.写log期间进程异常
3.write操作完成后(写日志、写内存都完成)异常
4.immutable memtable持久化过程异常
5.其它压缩异常
第2种情况发生,数据库重启读取log时,发现异常日志数据则丢弃该条日志数据,即视作这次用户写入失败
第1、3、4情况发生时,都可以通过读取redo日志文件中记录的写入操作来完成数据库的恢复。
一文彻底搞懂leveldb架构相关推荐
- 一文彻底搞懂前端监控 等推荐
大家好,我是若川.话不多说,这一次花了几个小时精心为大家挑选了20余篇好文,供大家阅读学习.本文阅读技巧,先粗看标题,感兴趣可以都关注一波,一起共同进步. 前端点线面 前端点线面 百度前端研发工程师, ...
- 一文快速搞懂Kudu到底是什么
文章目录 引言 文章传送门: Kudu 介绍 背景介绍 新的硬件设备 Kudu 是什么 Kudu 应用场景 Kudu 架构 数据模型 分区策略 列式存储 整体架构 Kudu Client 交互 Kud ...
- layer output 激活函数_一文彻底搞懂BP算法:原理推导+数据演示+项目实战(下篇)...
在"一文彻底搞懂BP算法:原理推导+数据演示+项目实战(上篇)"中我们详细介绍了BP算法的原理和推导过程,并且用实际的数据进行了计算演练.在下篇中,我们将自己实现BP算法(不使用第 ...
- opc服务器是硬件吗,opc是什么(一文彻底搞懂什么是OPC)
原标题:(opc是什么(一文彻底搞懂什么是OPC)) opc是什么(一文完全搞懂什么是OPC)从2000年终以来,我们就一直在运用OPC软件互操纵性范例,而那些正准备踏入和想要踏入工业自动化范畴的人们 ...
- 10分钟带你彻底搞懂微内核架构
文章目录 十分钟搞懂系列 什么是微内核架构? 如何实现微内核架构? 总结 十分钟搞懂系列 序号 标题 链接 1 10分钟带你彻底搞懂企业服务总线 https://blog.csdn.net/belon ...
- 一文彻底搞懂BP算法:原理推导+数据演示+项目实战(下篇)
在"一文彻底搞懂BP算法:原理推导+数据演示+项目实战(上篇)"中我们详细介绍了BP算法的原理和推导过程,并且用实际的数据进行了计算演练.在下篇中,我们将自己实现BP算法(不使用第 ...
- 一文彻底搞懂Mybatis系列(十六)之MyBatis集成EhCache
MyBatis集成EhCache 一.MyBatis集成EhCache 1.引入mybatis整合ehcache的依赖 2.类根路径下新建ehcache.xml,并配置 3.POJO类 Clazz 4 ...
- 手写简易版 React 来彻底搞懂 fiber 架构
React 16 之前和之后最大的区别就是 16 引入了 fiber,又基于 fiber 实现了 hooks.整天都提 fiber,那 fiber 到底是啥?它和 vdom 是什么关系? 与其看各种解 ...
- 一文彻底搞懂ROC曲线与AUC的概念
一文彻底搞懂ROC曲线与AUC的概念 1. ROC曲线的初级含义 1.1 精确率和召回率 1.2 ROC曲线的含义 2. ROC曲线如何绘制 3. ROC曲线和排序有什么关联? 4. AUC和基尼系数 ...
最新文章
- mysql opti_MySQL基础操作
- rmmod: can't change directory to '/lib/modules': No such file or directory问题解决
- 等差素数列(素数筛暴力)
- python爬虫面试题
- 定位到元素后获取其属性_Selenium界面自动化测试(4)(Python):元素定位及操作...
- json解析数组 nlohmann_json解析数组 nlohmann_Nlohmann json学习
- (转)Hibernate框架基础——映射普通属性
- 电脑硬件知识学习_计算机的发展史,你对硬件知识了解多少,带大家了解一下....
- SSL数字证书的签发及使用(服务器证书)
- 计算机组成原理本科生期末试卷答案,计算机组成原理本科生期末试题.doc
- com.android.gallery3d文件夹,如何在Android Gallery3D(cooliris)中显示特定文件夹?
- Python学习_100Days
- 英语发音规则---/ŋ/与/ŋg/的读音区别
- 这可能是世界第一座海上漂浮城市,浑身都是黑科技!
- Learning Deep Features for Discriminative Localization
- python网络数据采集 第二版_Python网络数据采集 (影印版)第2版
- 2020版KALI安装教程
- 京东有鸿蒙系统app,刘强东力挺华为鸿蒙,安卓版京东与鸿蒙版京东,差距不是一点点...
- 枪火——古龙之视觉化
- 【uni-app】uni-app实现聊天页面功能——功能篇(下)
热门文章
- FileInputStream中read()及read(byte b[])的用法
- 网络流和棒球赛淘汰问题 公平分配模板 足球联赛 UVa1306 The K-League
- vue自定义表单设计器思路
- linux快捷命令设置
- android Launcher3 动态设置一个快捷图标(添加快捷图标)
- JavaWeb细节——jstl导入eclipse报错
- [Unity] Generic 模式的动画混合和移动方向发生错误的解决办法:使用 Humanoid 模式
- Smoothing Images
- STM32CubeMX GCC工程Makefile内容详解
- WinAPI: OffsetRect - 移动矩形