leveldb多线程读写(大数据高并发解决方案)

在并发写入的时候,leveldb巧妙的利用一个时间窗口做batch写入,这部分代码值得一读:StatusDBImpl::Write(constWriteOptions&options,WriteBatch*my_batch){  //partA  Writerw(&mutex_);  w.batch=my_batch;  w.sync=options.syn…

大家好,又见面了,我是你们的朋友全栈君。

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

Status DBImpl::Write(const WriteOptions& options, WriteBatch* my_batch) {
  
//part A
  Writer w(&mutex_);
  w.batch = my_batch;
  w.sync = options.sync;
  w.done = false;

  //part B
  MutexLock l(&mutex_);
  writers_.push_back(&w);
  while (!w.done && &w != writers_.front()) {
    w.cv.Wait();
  }
  if (w.done) {
    return w.status;
  }
   
  // May temporarily unlock and wait.
  Status status = MakeRoomForWrite(my_batch == NULL);
  uint64_t last_sequence = versions_->LastSequence();
  Writer* last_writer = &w;
    //part C
  if (status.ok() && my_batch != NULL) {  // NULL batch is for compactions
    WriteBatch* 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_.

    //part D
    {
      mutex_.Unlock();
      status = log_->AddRecord(WriteBatchInternal::Contents(updates));
      if (status.ok() && options.sync) {
        status = logfile_->Sync();
      }
      if (status.ok()) {
        status = WriteBatchInternal::InsertInto(updates, mem_);
      }
      mutex_.Lock();
    }

    if (updates == tmp_batch_) tmp_batch_->Clear();

    versions_->SetLastSequence(last_sequence);
  }

//part E
  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;
  }

   //part F
  // Notify new head of write queue
  if (!writers_.empty()) {
    writers_.front()->cv.Signal();
  }

  return status;
}

     假设同时有w1, w2, w3, w4, w5, w6 并发请求写入。
  B部分代码让竞争到mutex资源的w1获取了锁。w1将它要写的数据添加到了writers_队列里去,此时队列只有一个w1, 从而其顺利的进行buildbatchgroup。当运行到(
part C)时mutex_互斥锁释放,之所以这儿可以释放mutex_,是因为其它的写操作都不满足队首条件,进而不会进入log和memtable写入阶段。这时(w2, w3, w4, w5, w6)会竞争锁,由于B段代码中不满足队首条件,均等待并释放锁了。从而队列可能会如(w3, w5, w2, w4).
  继而w1进行log写入和memtable写入。 当w1完成log和memtable写入后,则mutex_又锁住,这时(PART B)代码中队列因为获取不到锁则队列不会修改。
  随后(
part E)开始,w1被pop出来,由于ready==w, 并且ready==last_writer,所以到(
part F),唤醒了此时处于队首的w3.
      w3唤醒时,发现自己是队首,可以顺利的进行进入buildbatchgroup,在BuildBatchGroup函数中,遍历了目前所有的队列元素,形成一个update的batch,即将w3, w5, w2, w4合并为一个batch. 并将last_writer置为此时处于队尾的最后一个元素w4,(
part D)运行后,因为释放了锁资源,队列可能随着dbimpl::write的调用而更改,如队列状况可能为(w3, w5, w2, w4, w6, w9, w8).
   (
part D)的代码将w3, w5, w2, w4整个的batch写入log和memtable. 到(
part E),分别对w5, w2, w4进行了一次cond signal.当判断到完w4 == lastwriter时,则退出循环。(
part F)则对队首的w6唤醒,从而按上述步骤依次进行下去。
  这样就形成了多个并发write 合并为一个batch写入log和memtable的机制。

转载于:
http://www.cnblogs.com/cobbliu/p/6193164.html 若存在版权问题,请联系。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/127413.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • C++日志系统log4cxx使用总结[通俗易懂]

    C++日志系统log4cxx使用总结[通俗易懂]本文主要从log4cxx级别、layout、格式化、命名规则、Filter几个方面介绍。 一、log4cxx命名规则        Logger由一个String类的名字识别,logger的名字是大小写敏感的,且名字之间具有继承的关系,子名有父名作为前缀,用点号.分隔。如:x.y是x.y.z的父亲。根logger(rootlogger)是所有logger的祖先, 它具有如下属性:1…

    2022年6月17日
    34
  • ViewPager 详解(二)—详解四大函数

    ViewPager 详解(二)—详解四大函数前言:上篇中我们讲解了如何快速实现了一个滑动页面,但问题在于,PageAdapter必须要重写的四个函数,它们都各有什么意义,在上节的函数内部为什么要这么实现,下面我们就结合android的API说明,详细讲解一下。相关文章:1、《ViewPager详解(一)—基本入门》2、《ViewPager详解(二)—详解四大函数》3、《ViewPager详解(三)-…

    2022年7月22日
    8
  • 超详细MySQL安装及基本使用教程[通俗易懂]

    超详细MySQL安装及基本使用教程[通俗易懂]一、下载MySQL首先,去数据库的官网http://www.mysql.com下载MySQL。点击进入后的首页如下: 然后点击downloads,community,选择MySQLCommunityServer。如下图: 滑到下面,找到RecommendedDownload,然后点击gotodownloadpage。如下图: 点击download进入下载页面选择No…

    2022年4月27日
    48
  • ssh登录linux

    ssh登录linux2018-9-6上一篇提到用ssh登录centos好处很多,许多linux系统管理员都在用ssh。在windows下ssh客户端主要有puTTY、Xshell、secureCRT、sshsecureshell。linux下有openssh,这是个命令行工具。这篇主要将puTTY和Xshell的使用。puTTYpuTTY是开源免费软件。放恶意软件,建意到官网下载,或者百度、360、搜…

    2025年7月5日
    0
  • jenkins demo //TODO「建议收藏」

    jenkins demo //TODO「建议收藏」mkdir-p/var/jenkins_mountchmod777/var/jenkins_mountdockerrun-d-p9091:8080-p9092:50000-v/var/jenkins_mount:/var/jenkins_mount-v/etc/localtime:/etc/localtime-v/usr/share/apache-maven/apache-maven-3.8.1:/usr/local/maven–namejenkinsjenk

    2022年6月2日
    28
  • 数据库query用法_query方法

    数据库query用法_query方法1、以前写代码,总免不了要编写登录部分。在获取user的时候,只可能返回一个user实例,或者为null。以前使用以下方法实现:publicUserget(Stringname,Stringpassword){Sessionsession=HibernateUtil.getSessionFactory().openSession();String…

    2022年9月30日
    1

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号