[LevelDB] 写批处理过程详解

leveldb的write代码初看瞎搞一堆,细看则实为短小精悍。1 Status DBImpl::Write(const WriteOptions& options, WriteBatch* my_batch) {

 2  // -----A begin-------  3   Writer w(&mutex_);  4   w.batch = my_batch;  5   w.sync = options.sync;  6   w.done = false;  7   // -----A end  --------  8 9 
10   // -----B begin-------  
11   MutexLock l(&mutex_);  
12   writers_.push_back(&w);  
13   while (!w.done && &w != writers_.front()) {  
14     w.cv.Wait();  
15   }  
16   if (w.done) {  
17     return w.status;  
18   }  
19   // -----B end  -------  
20 
21   // May temporarily unlock and wait.  
22   Status status = MakeRoomForWrite(my_batch == NULL);  
23   uint64_t last_sequence = versions_->LastSequence();  
24   Writer* last_writer = &w;  
25   if (status.ok() && my_batch != NULL) {  // NULL batch is for compactions  
26     WriteBatch* updates = BuildBatchGroup(&last_writer);  
27     WriteBatchInternal::SetSequence(updates, last_sequence + 1);  
28     last_sequence += WriteBatchInternal::Count(updates);  
29 
30     // Add to log and apply to memtable.  We can release the lock  
31     // during this phase since &w is currently responsible for logging  
32     // and protects against concurrent loggers and concurrent writes  
33     // into mem_.  
34     {
35       // -----C begin-------  
36       mutex_.Unlock();  
37       // -----C end  -------  

      // add batch data to log files 38 status = log_->AddRecord(WriteBatchInternal::Contents(updates)); 39 if (status.ok() && options.sync) { 40 status = logfile_->Sync(); 41 } 42 if (status.ok()) { 43 status = WriteBatchInternal::InsertInto(updates, mem_); 44 } 45 // -----D begin------- 46 mutex_.Lock(); 47 // -----D end ------- 48 } 49 if (updates == tmp_batch_) tmp_batch_->Clear(); 50 51 versions_->SetLastSequence(last_sequence); 52 } 53 54 // -----E begin------- 55 while (true) { 56 Writer* ready = writers_.front(); 57 writers_.pop_front(); 58 if (ready != &w) { 59 ready->status = status; 60 ready->done = true; 61 ready->cv.Signal(); 62 } 63 if (ready == last_writer) break; 64 } 65 // -----E end ------- 66 67 68 // -----F begin------- 69 // Notify new head of write queue 70 if (!writers_.empty()) { 71 writers_.front()->cv.Signal(); 72 } 73 // -----F end------- 74 75 return status; 76 }

    如上,A段代码定义一个Writer w, w的成员包括了batch信息,同时初始化了一个条件变量成员(port::CondVar)

  假设同时有w1, w2, w3, w4, w5, w6 并发请求写入。

  B段代码让竞争到mutex资源的w1获取了锁。添加到writers队列里去,此时队列只有一个w1, 从而其顺利的进行BuildBatchGroup。当运行到c段代码时,mutex互斥锁释放,这时(w2, w3, w4, w5, w6)会竞争锁,由于B段代码中不满足队首条件,均等待并释放锁了。从而队列可能会如(w3, w5, w2, w4).

  继而w1进行log写入和memtable写入,之所以这里在无锁状况下时安全的,因为其它的写操作都不满足队首条件,进而不会进入log和memtable写入阶段。 当w1完成log和memtable写入后,进入d段代码,则mutex又锁住,这时B段代码中队列因为获取不到锁则队列不会修改。

  进入E段代码后,w1被pop出来,由于reader==w, 并且ready==last_writer,所以直接到F段代码,唤醒了此时处于队首的w3.

  w3唤醒时,发现自己是队首,可以顺利的进行进入BuildBatchGroup,在该函数中,遍历了目前所有的队列元素,形成一个update的batch,即将w3, w5, w2, w4合并为一个batch. 并将last_writer置为此时处于队尾的最后一个元素w4,c段代码运行后,因为释放了锁资源,队列可能随着DBImpl::Write的调用而更改,如队列状况可能为(w3, w5, w2, w4, w6, w9, w8).

  C段和D段间的代码将w3, w5, w2, w4整个的batch写入log和memtable. 到E段时,分别对w5, w2, w4进行了一次cond signal.当判断到完w4 == lastwriter时,则退出E段代码。F段则对队首的w6唤醒,从而按上述步骤依次进行下去。

  这样就形成了多个并发write 合并为一个batch写入log和memtable的机制。

转载于:https://www.cnblogs.com/mh1092/p/9936484.html

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

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

相关文章

关于excel vba 使用CopyFromRecordset出现格式问题的解决方法

关于excel vba 使用CopyFromRecordset出现格式问题的解决方法 出现问题的写法: With ActiveSheet .Name k(i) For num 1 To UBound(myArray) .Cells(1, num) myArray(num, 1) Next num .rang…

python histo 改变 bins 大小_在Python中显示具有非常不均匀的bin宽度的直方图

这是直方图为了生成这个图,我做了:bins np.array([0.03, 0.3, 2, 100])plt.hist(m, bins bins, weightsnp.zeros_like(m) 1. / m.size)但是,正如您所注意到的,我想绘制每个数据点的相对频率的直方图,只有3个不同大小的区间:bin1 0.03 – > 0.3bin…

parted工具详解

通常我们用的比较多的一般都是fdisk工具来进行分区,但是现在由于磁盘越来越廉价,而且磁盘空间越来越大;而fdisk工具他对分区是有大小限制的,它只能划分小于2T的磁盘。但是现在的磁盘空间很多都已经是远远大于2T了,甚至…

Python安装pyinstaller模块的错误:NO module name “setuptools“

出现改pyinstaller安装错误常见问题是:pip版本或者setuptools包版本过低。 出现上图提示的错误后,升级一下setuptools包: (1)pip install --upgrade setuptools (2)pip install pyinstaller

jvm ide_预热JVM –超快速生产服务器和IDE

jvm ide几个月前,我正在阅读Java中的复杂事件处理以及实现低延迟的方法。 在我长达一个小时的研究结束时,我发现即使您的应用程序编写正确并且您的方法主要在0(log n)的时间内运行,并且您使用的是某些尖端的硬件解决方…

Python 项目打包成可执行程序命令

一、安装pyinstaller (1)winR输入cmd,打开命令窗口 2)安装pyinstaller,安装指令:pip install pyinstaller 二、打包 1,切换到打包程序目录 例:需要打包程序目录为:D:\pythonfun\useringfunct…

软RAID-mdadm折腾小记

RAID --- 磁盘阵列,简言之,用来提高硬盘的利用率和速度RAID种类(理论):RAID 0 : 读写性能(最少两块硬盘) --- 硬盘使用量是所有硬盘大小之和,性能是所有硬盘之和RAID 1 : 读写性能,冗余性(最少两块硬盘) --- 空间利用率:所有磁盘中最小的那块(n/2); 读性能接近RAID0,写性能较r…

python学习笔记:第19天 类的约束、异常、MD5和logging

目录 一、类的约束二、异常处理:三、MD5加密四、日志(logging模块)一、类的约束 真正写写项目的代码时都是多人协作的,所以有些地方需要约束程序的结构。也就是说,在分配任务之前就应该把功能定义好,然后分…

新ANTLR 4.6的重要更改

自从上一个主要版本发布以来,已经过去了将近一年的时间,推出了新的ANTLR版本: 4.6 。 有很多新闻:新的目标,更好的性能,更好的错误处理以及ANTLR本身开发中的一些改进。 新目标 影响最大的新闻可能是新目标…

strcmp可以比较数组么_C语言数组越界了,后果很严重,如何避免?

素材来源:嵌入式ARM所谓的数组越界,简单地讲就是指数组下标变量的取值超过了初始定义时的大小,导致对数组元素的访问出现在数组的范围之外,这类错误也是 C 语言程序中最常见的错误之一。在 C 语言中,数组必须是静态的。…

MongoDB 问题123

MongoDB 是非关系型数据库中的一种。 出于某些原因,我们用了Mongo。他们说Mongo的最大特点是快。 不过这种快是以空间换时间的代价而得来的。 这个空间代价包括 1.DB至少占用64M(好像是这个数字,因为我们的DB实际往往只有几M,但却要占用那么多&#xff0…

两个excel文档查找相同选项后替换_看似普通的查找和替换功能,用好了,能让你的工作效率翻一番...

关注【新精英充电站】能力提升看得见!在Word中,查找和替换功能是编辑文档时时常要用到的重要功能,它能帮助我们快速将文档或表格中查找到的内容或格式等替换为指定的内容或格式,特别是遇到大量需要修改的相同文字内容或格式时非常…

Mongodb内存管理和使用情况情况查询

overview MongoDB使用的是内存映射存储引擎,即Memory Mapped Storage Engine,简称MMAP。MMAP可以把磁盘文件的一部分或全部内容直接映射到内存,这样文件中的信息位置就会在内存中有对应的地址空间,这时对文件的读写可以直接用指针来做&#…

mapreduce文本排序_MapReduce:通过数据密集型文本处理

mapreduce文本排序自上次发布以来已经有一段时间了,因为我一直忙于Coursera提供的一些课程。 有一些非常有趣的产品,值得一看。 前一段时间,我购买了Jimmy Lin和Chris Dyer的MapReduce数据密集型处理程序 。 本书以伪代码格式介绍了几种关键的…

nginx根据参数转发到不同服务器_Nginx服务器之负载均衡策略

一、关于Nginx的负载均衡在服务器集群中,Nginx起到一个代理服务器的角色(即反向代理),为了避免单独一个服务器压力过大,将来自用户的请求转发给不同的服务器。二、Nginx负载均衡策略负载均衡用于从“upstream”模块定义…

同步异步与协程

目录: 同步/异步 异步回调 协成 线程队列 同步|异步: 线程的三种状态:   1.就绪   2.运行   3.阻塞阻塞和非阻塞描述的是运行的状态阻塞 :遇到了IO操作,代码卡住,无法执行下一行,CPU会切换到其他任务非阻塞 :与阻塞相反,代码正在执行(运行状态) 或处于就绪状态…

Linux禁止非WHEEL用户使用SU命令

通常情况下,一般用户通过执行“su -”命令、输入正确的root密码,可以登录为root用户来对系统进行管理员级别的配置。 但是,为了更进一步加强系统的安全性,有必要建立一个管理员的 组,只允许这个组的用户来执行“su -”…

代理的JavaOne 2016观察

我无法参加JavaOne 2016,因此很高兴在线上看到大量资源,这些资源使我能够基于JavaOne 2016内容进行观察。 我在本文中引用并简要描述了其中的一些JavaOne 2016资源,并根据这些资源的使用添加了我自己的一些观察结果。 正如Katharine在JavaOne…

resnet过拟合_重读经典:完全解析特征学习大杀器ResNet

公众号关注 “ML-CVer”设为 “星标”,DLCV消息即可送达!作者丨刘昕宸知乎来源丨https://zhuanlan.zhihu.com/p/268308900编辑丨极市平台导读 通过堆叠神经网络层数(增加深度)可以非常有效地增强表征,提升特征学习效果,但是会出现…

Java开发笔记(二十三)数组工具Arrays

数组作为一种组合形式的数据类型,必然要求提供一些处理数组的简便办法,包括数组比较、数组复制、数组排序等等。为此Java专门设计了Arrays工具,该工具包含了几个常用方法,方便程序员对数组进行加工操作。Arrays工具的方法说明如下…