[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
[LevelDB] 写批处理过程详解相关推荐
- Hadoop学习之Mapreduce执行过程详解
一.MapReduce执行过程 MapReduce运行时,首先通过Map读取HDFS中的数据,然后经过拆分,将每个文件中的每行数据分拆成键值对,最后输出作为Reduce的输入,大体执行流程如下图所示: ...
- Android签名机制之---签名验证过程详解
一.前言 今天是元旦,也是Single Dog的嚎叫之日,只能写博客来祛除寂寞了,今天我们继续来看一下Android中的签名机制的姊妹篇:Android中是如何验证一个Apk的签名.在前一篇文章中我们 ...
- Linux开启动过程详解
Linux开启动过程详解 Linux启动过程 前言: Linux是一种自由和开放源代码的类UNIX操作系统.该操作系统的内核由林纳斯·托瓦兹在1991年10月5日首次发布.在加上用户空间的应用程序之后 ...
- 操作系统之多线程编程—读者优先/写者优先详解
操作系统之进程调度--优先权法和轮转法(附上样例讲解) 操作系统之银行家算法-详解流程及案例数据 操作系统之多线程编程-读者优先/写者优先详解 操作系统之存储管理--FIFO算法和LRU算法 操作系统 ...
- Mysql加锁过程详解(2)-关于mysql 幻读理解
Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...
- python属性使用教程_Python对象的属性访问过程详解
只想回答一个问题: 当编译器要读取obj.field时, 发生了什么? 看似简单的属性访问, 其过程还蛮曲折的. 总共有以下几个step: 1. 如果obj 本身(一个instance )有这个属性, ...
- Java web 开发的概念、环境配置、创建项目过程详解(Eclipse)
Java Web 开发 Java Web 开发概念 搭建过程 详解 在eclipse创建Dynamic Web Project 创建时选择Tomcat的版本 创建项目成功 eclipse环境下如何配置 ...
- #转载:杨辉三角形实现过程详解-c语言基础
杨辉三角形实现过程详解-C语言基础 十一一个人 2018-12-26 06:45:45 6465 收藏 28 最后发布:2018-12-26 06:45:45首发:2018-12-26 06:45:4 ...
- U-Boot 之三 U-Boot 源码文件解析及移植过程详解
在之前的博文 Linux 之八 完整嵌入式 Linux 环境介绍及搭建说明 中我们说了要一步步搭建整个嵌入式 Linux 运行环境.我所使用的硬件平台及整个要搭建的嵌入式 Linux 环境见博文 ...
最新文章
- wpf listview mysql_Kivy:使用MySQL的Kivy页面的Listview实现
- 不是变量 win10_在win10下安装manim
- 【Android】Apk安装和删除
- mysql 取 映射数据库中_JAVA与数据库MySQL相连接
- python函数结构_PYTHON 之结构体,全局变量,函数参数,lambda编程 等
- 数据结构与算法——二叉排序树详解以及代码实现
- tdk怎么设置_网站tdk如何正确的设置
- python数据挖掘笔记】十八.线性回归及多项式回归分析四个案例分享
- 学习OpenCV时 ,添加:#includeopencv2/core/core.hpp等头文件出现无法编译的错误
- windows 安装 mysql 5.6
- python strip() 方法
- python数据框添加一列无列名_Pandas只使用列名创建空数据框
- matlab积分超过最大值,MATLAB 定积分上限是变量a,如何求解目标函数关于变量a的最大值?谢谢...
- 对话「平衡车之父」:把Solowheel带回中国
- 大学计算机云计算与虚拟服务实验,虚拟化与云计算实验报告.doc.pdf
- 工控网络安全学习路线
- 新一代打包神器parcel简介
- web网页制作期末大作业——蓝色的异清轩个人博客(6页) 个人博客模板源码异清轩博客
- 什么是ISO?ISO增值的作用
- C++环境下部署深度学习模型方案
热门文章
- linux mysql 忘记root密码_Linux MySQL忘记root密码解决方案
- LeetCode 07. 整数反转
- linux监控nginx占用,使用zabbix 2.4 监控nginx
- mysql开发问题解决_开发过程中mysql常见问题的解决方法
- 公路多孔箱涵设计_【公路常识中篇】公路路基边坡滑坡防护设计和预防
- java 实现按规则自增功能_java运算符详解 - osc_74vaali6的个人空间 - OSCHINA - 中文开源技术交流社区...
- pat 乙级 1021 个位数统计(C++)
- 光端机的几种物理接口类型
- 【渝粤教育】国家开放大学2018年春季 8634-22TAndroid智能手机编程 参考试题
- 【渝粤题库】陕西师范大学200641高等数学作业(高起专、专升本)