在并发写入的时候,leveldb巧妙地利用一个时间窗口做batch写入,这部分代码值得一读:

Status DBImpl::Write(const WriteOptions& options, WriteBatch* my_batch) {// A begin Writer w(&mutex_);w.batch = my_batch;w.sync = options.sync;w.done = false;// A end// B begin MutexLock l(&mutex_);writers_.push_back(&w);while (!w.done && &w != writers_.front()) {w.cv.Wait();}if (w.done) {return w.status;}// B end// May temporarily unlock and wait.Status status = MakeRoomForWrite(my_batch == NULL);uint64_t last_sequence = versions_->LastSequence();Writer* last_writer = &w;if (status.ok() && my_batch != NULL) {  // NULL batch is for compactionsWriteBatch* updates = BuildBatchGroup(&last_writer);WriteBatchInternal::SetSequence(updates, last_sequence + 1);last_sequence += WriteBatchInternal::Count(updates);// Add to log and apply to memtable.  We can release the lock// during this phase since &w is currently responsible for logging// and protects against concurrent loggers and concurrent writes// into mem_.{mutex_.Unlock();status = log_->AddRecord(WriteBatchInternal::Contents(updates));bool sync_error = false;if (status.ok() && options.sync) {status = logfile_->Sync();if (!status.ok()) {sync_error = true;}}if (status.ok()) {status = WriteBatchInternal::InsertInto(updates, mem_);}mutex_.Lock();if (sync_error) {// The state of the log file is indeterminate: the log record we// just added may or may not show up when the DB is re-opened.// So we force the DB into a mode where all future writes fail.RecordBackgroundError(status);}}if (updates == tmp_batch_) tmp_batch_->Clear();versions_->SetLastSequence(last_sequence);}while (true) {Writer* ready = writers_.front();writers_.pop_front();if (ready != &w) {ready->status = status;ready->done = true;ready->cv.Signal();}if (ready == last_writer) break;}// Notify new head of write queueif (!writers_.empty()) {writers_.front()->cv.Signal();}return status;
}

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

  B部分代码让竞争到mutex资源的w1获取了锁。w1将它要写的数据添加到了writers_队列里去,此时队列只有一个w1, 从而其顺利的进行buildbatchgroup。当运行到34行时mutex_互斥锁释放,之所以这儿可以释放mutex_,是因为其它的写操作都不满足队首条件,进而不会进入log和memtable写入阶段。这时(w2, w3, w4, w5, w6)会竞争锁,由于B段代码中不满足队首条件,均等待并释放锁了。从而队列可能会如(w3, w5, w2, w4).

  继而w1进行log写入和memtable写入。 当w1完成log和memtable写入后,进入46行代码,则mutex_又锁住,这时B段代码中队列因为获取不到锁则队列不会修改。

  随后59行开始,w1被pop出来,由于ready==w, 并且ready==last_writer,所以直接到71行代码,唤醒了此时处于队首的w3.

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

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

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

  

转载于:https://www.cnblogs.com/cobbliu/p/6193164.html

leveldb - 并发写入处理相关推荐

  1. 从JoinBatchGroup 代码细节 来看Rocksdb的相比于leveldb的写入优势

    文章目录 1. Rocksdb写入模型 2. LevelDB写入的优化点 3. Rocksdb 的优化 1. Busy Loop 2. Short Wait -- SOMETIMES busy Loo ...

  2. C#使用读写锁三行代码简单解决多线程并发写入文件时线程同步的问题

    在开发程序的过程中,难免少不了写入错误日志这个关键功能.实现这个功能,可以选择使用第三方日志插件,也可以选择使用数据库,还可以自己写个简单的方法把错误信息记录到日志文件. 选择最后一种方法实现的时候, ...

  3. Kafka如何实现每秒上百万的超高并发写入?

    这篇文章来聊一下 Kafka 的一些架构设计原理,这也是互联网公司面试时非常高频的技术考点. Kafka 是高吞吐低延迟的高并发.高性能的消息中间件,在大数据领域有极为广泛的运用.配置良好的 Kafk ...

  4. Kafka如何实现每秒上百万的超高并发写入?掌握好面试给你打满分!

    这篇文章来聊一下 Kafka 的一些架构设计原理,这也是互联网公司面试时非常高频的技术考点. Kafka 是高吞吐低延迟的高并发.高性能的消息中间件,在大数据领域有极为广泛的运用.配置良好的 Kafk ...

  5. MongoDB与Tokyo Tyrant性能比较(2):并发写入操作

    在上一次的测试中我们比较了MongoDB与Tokyo Tyrant的Table Database两种存储方式的性能.不过由于条件限制,我只能在自己的MBP上测试,而这至少会带来两个问题.首先,真实环境 ...

  6. TiDB 高并发写入常见热点问题及规避方法

    作者:姚维 本文通过阐述一个高并发批量写入数据到 TiDB 的典型场景中,TiDB 中常见的问题,给出一个业务的最佳实践,避免业务在开发的时候陷入 TiDB 使用的 "反模式". ...

  7. 加米谷大数据干货:Kafka如何实现每秒上百万的超高并发写入?

    加米谷大数据为你带来这篇文章来聊一下 Kafka 的一些架构设计原理,这也是互联网公司面试时非常高频的技术考点. Kafka 是高吞吐低延迟的高并发.高性能的消息中间件,有极为广泛的运用.配置良好的 ...

  8. Elasticsearch高并发写入优化的开源协同经历

    导语:在腾讯金融科技数据应用部的全民 BI 项目里,我们每天面对超过 10 亿级的数据写入,提高 ES 写入性能迫在眉睫,在最近的一次优化中,有幸参与到了 Elasticsearch 开源社区中. 本 ...

  9. 如何处理高并发写入mysql_如何处理高并发情况下的DB插入

    转载以便以后学习使用,谢谢! 插入数据库,在大家开发过程中是很经常的事情,假设我们有这么一个需求: 1.  我们需要接收一个外部的订单,而这个订单号是不允许重复的 2.  数据库对外部订单号没有做唯一 ...

最新文章

  1. TBluetoothLE.OnDisconnectDevice
  2. InfoQ专访网易云陈谔:用微服务体系满足企业数字化转型需求
  3. 标准缺失成发展阻碍 智能家居普及之路任重而道远
  4. mysql 连接数的最大数
  5. cognito_将Spring Boot应用程序与Amazon Cognito集成
  6. glassfish_重写到边缘–充分利用它! 在GlassFish上!
  7. 2018CES智能硬件与新技术盘点
  8. QQ动态头像和动态主页
  9. [改善Java代码]枚举项的数量限制在64个以内
  10. 从Preact了解一个类React的框架是怎么实现的(二): 元素diff
  11. matlab程序中for,matlab中的for循环
  12. gorm存指针数据_C语言重点——指针篇(一篇让你完全搞懂指针)
  13. ArcGIS模型操作
  14. 1.Chrome开发者工具不完全指南(一、基础功能篇)
  15. ping and traceroute(tracert)
  16. mysql hyperloglog_Redis HyperLogLog
  17. 2023苏州科技大学计算机考研信息汇总
  18. redis lpush WRONGTYPE Operation against a key holding the wrong kind of value
  19. Sloth演示程序及源代码发布
  20. 家里装电线时,为啥说“走顶”比“走地”好

热门文章

  1. JavaScript 概述
  2. 两种方式实现登录跳转新窗体
  3. 3D开发-AR技术基础
  4. Python入门学习-DAY27- isinstance与issubclass、反射、内置方法
  5. ASP.NET的IIS映射
  6. linux远程开启不挂起的服务
  7. [ZJOI 2006]书架
  8. 1014-新浪微博(数据 cell )
  9. [翻译]自定义Sharepoint的登陆页面
  10. 在C#后代码里使用IE WEB Control TreeView