首页 > 其他分享 >leveldb的MVCC并发控制策略

leveldb的MVCC并发控制策略

时间:2023-02-10 22:23:31浏览次数:45  
标签:文件 leveldb sst 合并 计数 version 引用 MVCC 控制策略

MVCC多版本是一个解决并发问题的模型,或者说是一种设计思路。

why MVCC?

如果有一份数据,无论它是存储在内存里还是磁盘上,当我们读取数据时可能有写操作正在修改它。传统思路就是将数据用一把锁保护起来:

  • 读之前加读锁,这样就不会有写操作。
  • 写之前加写锁,这样就不会有读操作和其他写操作。

如果数据是内存里的一个哈希表,那么锁的代价还可以忍受,几乎总是瞬间可以完成。

然而存储系统一般都要和磁盘打交道,读请求是从磁盘上读取一个文件的某个偏移量

写请求可能需要删除旧的文件创建一个修改过的新文件一般存储不会覆盖修改数据,因为异常时可能写坏数据)。

如果仍为了保护数据而上锁,那么磁盘的缓慢操作将导致锁占用时间很长,从而直接降低了系统吞吐。

如果不上锁,那么极有可能正在读某个文件的同时,文件被删除了,导致严重错误。

这就是MVCC多版本技术出现的背景环境。

how mvcc?

假设一个场景:读操作会去磁盘扫描sst文件查找对应的数据,而策略job可能恰好正在合并遍历中的某sst文件,同时向合并后的sst文件输出中,最后还会删除掉旧的sst文件。

这意味着,正在读的sst文件可能被删除,或者正在输出中(不完整)。

按照我们悲观锁的思路,直接加一把大锁,那么读请求期间写请求无法进行,漫长的写期间读请求不能进行,基本这个leveldb就没法用了。

leveldb采用MVCC避免大锁,这里引入了几个概念:

1.version edit:记录sst文件集合的变化。当合并N个sst生成1个大sst,被合并的sst不再有意义,合并生成的新sst包含了它们的数据,version edit记录的就是:合并了哪些sst,新增了哪个sst。

2.version:代表一个版本,记录了数据库由哪些sst文件组成。当磁盘合并发生后,对应的version edit施加到最新的version上,从而产生新的version,它记录了当前最新的数据库sst集合。

3.version_set:指向最新的version。

version set全局唯一,其中current_指针指向最新的version:

VersionSet {
 // 实际的 Env
 Env* const env_;
 // db 的数据路径
 const std::string dbname_;
 // 正在服务的 Version 链表
 Version dummy_versions_;
 // 当前最新的的 Version
 Version* current_;

这是version,files_保存了该版本数据库的所有sst文件。

class Version {
 ......
 // 属于的 VersionSet
 VersionSet* vset_;
 // 链表指针
 Version* next_;
 Version* prev_;
 // 引用计数
 int refs_;

 // 每个 level 的所有 sstable 元信息。
 // files_[i]中的 FileMetaData 按照 FileMetaData::smallest 排序
 std::vector<FileMetaData*> files_[config::kNumLevels];

next_,prev_是链表,说明多个version是串在一起的。这里就容易产生几个好奇:

1.为什么会有多个version?
2.version是怎么产生的?

回想合并的过程,N个sst文件merge到1个sst文件后,虽然N个sst文件已经没有意义,但是leveldb并不会立即删除它们,这是为什么呢?这就涉及到读请求了。

某个时刻,读请求会根据version_set里的current_找到最新version,并在这个version里保存的sst文件集合中寻找目标数据。

此后假设发生了合并并产生了新的version,新version将更新到version_set的current_字段成为新的链表头。如果此时立即删除被合并的sst文件,那么正在进行中的读请求就会出错

所以删除sst文件的动作并不是立即发生的。同时,因为读请求依据的是旧版本的version(sst文件集合),所以新合并生成的sst并不会被该读请求扫描到。

在实现上来说,读请求引用了旧版本的version,而写请求需要设置新版本的version,那么旧版本的version何时释放内存呢?

这里就采用了引用计数机制,最新的version默认是1个引用计数并保存在version_set的链表头部(current_),当读请求到来后会对version_set的current_增加1个引用计数。此后发生合并生成新version替换current_时,先释放旧version的1个引用计数(还剩余1个由读请求持有),然后替换current_为新的version对象。

当读请求结束后,会释放旧version的最后1个引用计数,此时引用计数降低为0,旧版本version进入析构函数。这里涉及另外一个重要设计,我们知道之前写请求(合并sst)完成时并没有删除被合并的sst文件,其目的是因为之前的读请求可能正在访问旧sst文件,特意延迟了删除操作

删除应该延迟到什么时候呢?其实只要涉及到这种资源持有问题一般都是采用引用计数,在version中的files中保存的FileMetaData也是基于引用计数的共享内存。

当合并旧version+version edit生成新version时,旧version中没有被合并的sst文件对应的FileMetaData的引用计数将+1并保存到新version中

而被合并的sst文件的FileMetaData的引用计数保持不变, 但不保存到新version中。

当替换current_为新version时候,会首先释放旧version的1个引用计数,从而进入旧version析构。

在旧version析构中,会释放它的每个FileMetaData的1个引用计数,对于那些在新version中已经被合并的sst文件来说,引用计数减少为0将完成最终删除。

可见,leveldb的MVCC实际上由几个重要部分组成:

  • sst文件的不变性:只合并生成新sst而不覆盖旧的,保障多版本都可以读到属于自己的数据。
  • version引用计数:保证某版本所有sst文件的资源有效性。
  • FileMetaData引用计数:保证单个sst文件在多version下的资源有效性。

标签:文件,leveldb,sst,合并,计数,version,引用,MVCC,控制策略
From: https://www.cnblogs.com/lygin/p/17110392.html

相关文章

  • MySQL 的 MVCC 的工作原理
    InnoDB引擎通过什么技术来保证事务的四个特性的呢?持久性是通过redolog(重做日志)来保证的;原子性是通过undolog(回滚日志)来保证的;隔离性是通过MVCC(多版本并发控制)......
  • 浅析MySql中的MVCC机制
    前言本文将分析mvcc的机制和工作原理并举例说明。话不多说,直入主题MVCC机制是什么MVCC,英文全称MultiversionConcurrencyControl,多版本并发控制。简单理解,就是相当于给......
  • m基于GA遗传算法的电动汽车有序充电控制策略matlab仿真
    1.算法描述首先介绍MATLAB部分的遗传算法的优化算法介绍:遗传算法的原理遗传算法GA把问题的解表示成“染色体”,在算法中也即是以二进制编码的串。并且,在执行遗传算......
  • m基于GA遗传算法的电动汽车有序充电控制策略matlab仿真
    1.算法描述 首先介绍MATLAB部分的遗传算法的优化算法介绍:        遗传算法的原理        遗传算法GA把问题的解表示成“染色体”,在算法中也即是以二......
  • springboot~WebMvcConfigurer详解
    1.前言WebMvcConfigurer配置类其实是Spring内部的一种配置方式,采用JavaBean的形式来代替传统的xml配置文件形式进行针对框架个性化定制,可以自定义一些Handler,Interceptor......
  • MySQL之MVCC总结理解
    前置知识涉及到的几个概念:隐藏字段,undolog,readview(每个表中的)隐藏字段:最后修改记录的事务id,回滚指针undolog:在插入/更新数据的时候记录回滚日志当前读:读取的是记......
  • 区块链leveldb数据库安装
    一、首先,需要在电脑上安装boost库。下载地址在这里,下载压缩包之后解压,Indexofmain/release/1.79.0/source。解压完成后在解压好的文件夹里面进入cmd,之后运行bootstrip.......
  • mvcc
    本文转载自 https://article.itxueyuan.com/66wkm0 Multi-VersionConcurrencyControl,即多版本并发控制,主要是为了提高数据库的并发性能。同一行数据平时发生读写请......
  • leveldb在Windows和Linux上编译
    leveldb在Windows和Linux上编译 LevelDB是Google传奇工程师JeffDean和SanjayGhemawat开源的KV存储引擎(而非SQL),它是一种非关系型数据库。leveldb只有一层,即objects,也即key......
  • 浅谈InnoDB存储引擎的MVCC机制
    文章目录​​一、数据库事务隔离级别​​​​1、事务原则​​​​2、4种隔离级别​​​​3、会出现的3种问题​​​​二、MVCC概念​​​​1、基本结构​​​​2、字段介绍......