MongoDB数据缓存刷新机制

日期: 2011-07-13 作者:taobaodba 来源:TechTarget中国 英文

  最近配合好几个项目测试了MongoDB的写入性能。在内存没有用尽的情况下,虽然MongoDB只有一个更新线程,写入还是非常快的,基本上能达到25000/s以上(索引数据用uuid_generate_randome和uuid_unparse随机产生)。当内存用尽开始往磁盘上刷脏页的时候,性能有非常大的波动,即使调整了syncdelay也没有太大改善。在测试中还出现了一个莫名其妙的情况:MongoDB会间歇性地释放文件系统的cache。除了直接删除表空间之外,很难想到有什么动作可以诱发这个现象。在MongoDB开发者论坛里描述了这个现象,但是Eliot Horowitz认为MongoDB内部并没有代码会释放文件系统cache。那么,让我们去源码里面看一下MongoDB缓存和刷新数据的机制。

  首先找到mongod的入口(db/db.cpp),发现MongoDB的初始化步骤非常简单,概括起来就以下三步:

  int main(int argc, char* argv[], char *envp[] )
  {
  …
  Module::configAll( params );
  dataFileSync.go();
  …
  initAndListen(cmdLine.port, appsrvPath);
  …
  }

  显然,dataFileSync就是我们感兴趣的那个类。dataFileSync类派生自BackgroundJob类,而BackgroundJob主要的功能就是生成一个后台线程并指派任务。数据的刷新是一个不断执行的后台任务,在dataFileSync.run()里面可以找到刷数据的相关代码:

  void run()
  {
  …
  Date_t start = jsTime();
  int numFiles = MemoryMappedFile::flushAll( true );
  time_flushing = (int) (jsTime() – start);
  globalFlushCounters.flushed(time_flushing);
  …
  }

  从这一段代码看,MongoDB会在syncdelay设定的周期内,采取同步的形式刷新所有的脏数据。再看一下flushAll是怎么刷新所有数据的:

 int MongoFile::flushAll( bool sync )
  {
  …
  set seen;
  while ( true ){
  auto_ptr f;
  {
  rwlock lk( mmmutex , false );
  for ( set::iterator i = mmfiles.begin(); i != mmfiles.end(); i++ ){
  MongoFile * mmf = *i;
  if ( ! mmf )
  continue;
  if ( seen.count( mmf ) )
  continue;
  f.reset( mmf->prepareFlush() );
  seen.insert( mmf );
  break;
  }
  }
  if ( ! f.get() )
  break;
  f->flush();
  }
  return seen.size();
  }

  上面这一段代码实现的功能很简单,就是把mmfiles中所有MongoFile指针所引用的对象都flush()一次。不过在执行flush()函数之前,需要先执行prepareFlush()确保这个对象是可以执行flush()函数的。下面是最后真正执行刷新操作的代码:

  void MemoryMappedFile::flush(bool sync)
  {
  if ( view == 0 || fd == 0 )
  return;
  if ( msync(view, len, sync ? MS_SYNC : MS_ASYNC) )
  problem() << “msync ” << errnoWithDescription() << endl;
  }

  终于刷新到磁盘了,呵呵。不过这篇blog只涉及到了数据刷新的代码,至于如何缓存,且听下回分解。

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

电子邮件地址不会被公开。 必填项已用*标注

敬请读者发表评论,本站保留删除与本文无关和不雅评论的权力。

相关推荐