mongodb - DataFileSync 定期检查情况内存文件

本文深入探讨MongoDB中DataFileSync线程的工作原理,重点分析其如何通过定期清空内存映射文件来确保数据同步。文章详细解释了flushAll方法的具体实现及内部循环设计的原因。

main -》 mongoDbMain ->  dataFileSync.go -> DataFileSync -> run
该线程不停运行下面的while循环。

可以看出每次检查的时间间隔1分钟。

这里主要的功能就是清空内存文件:    MemoryMappedFile::flushAll

 419         void run() {                                                             
 420             Client::initThread( name().c_str() );                                
 421             if( cmdLine.syncdelay == 0 )                                         
 422                 log() << "warning: --syncdelay 0 is not recommended and can have strange performance" << endl;
 423             else if( cmdLine.syncdelay == 1 )                                    
 424                 log() << "--syncdelay 1" << endl;                                
 425             else if( cmdLine.syncdelay != 60 )                                   
 426                 LOG(1) << "--syncdelay " << cmdLine.syncdelay << endl;           
 427             int time_flushing = 0;                                               
 428             while ( ! inShutdown() ) {                                           
 429                 _diaglog.flush();                                                
 430                 log() << "[KAI] DataFileSync, start while" << endl;              
 431                 if ( cmdLine.syncdelay == 0 ) {                                  
 432                     // in case at some point we add an option to change at runtime
 433                     sleepsecs(5);                                                
 434                     continue;                                                    
 435                 }                                                                
 436                                                                                  
 437                 sleepmillis( (long long) std::max(0.0, (cmdLine.syncdelay * 1000) - time_flushing) );
 438                 log() << "[KAI] DataFileSync, start while 2" << endl;                                                                                                                                                                   
 439                                                                                  
 440                 if ( inShutdown() ) {                                            
 441                     // occasional issue trying to flush during shutdown when sleep interrupted
 442                     break;                                                       
 443                 }                                                                
 444                                                                                  
 445                 Date_t start = jsTime();                                         
 446                 int numFiles = MemoryMappedFile::flushAll( true );               
 447                 time_flushing = (int) (jsTime() - start);                        
 448                 log() << "[KAI] DataFileSync, start while 3" << endl;            
 449                                                                                  
 450                 _flushed(time_flushing);                                         
 451                                                                                  
 452                 if( logLevel >= 1 || time_flushing >= 10000 ) {                  
 453                     log() << "flushing mmaps took " << time_flushing << "ms " << " for " << numFiles << " files" << endl;
 454                 }                                                                
 455             }                                                                    
 456         }                                          



日志:

Fri Mar  8 14:18:20.824 [DataFileSync] [KAI] DataFileSync, start while
Fri Mar  8 14:19:20.810 [DataFileSync] [KAI] DataFileSync, start while 2
Fri Mar  8 14:19:20.838 [DataFileSync] [KAI] DataFileSync, start while 3
Fri Mar  8 14:19:20.838 [DataFileSync] [KAI] DataFileSync, start while
Fri Mar  8 14:20:20.837 [DataFileSync] [KAI] DataFileSync, start while 2
Fri Mar  8 14:20:20.838 [DataFileSync] [KAI] DataFileSync, start while 3
Fri Mar  8 14:20:20.838 [DataFileSync] [KAI] DataFileSync, start while
Fri Mar  8 14:21:20.838 [DataFileSync] [KAI] DataFileSync, start while 2
Fri Mar  8 14:21:20.855 [DataFileSync] [KAI] DataFileSync, start while 3
Fri Mar  8 14:21:20.855 [DataFileSync] [KAI] DataFileSync, start while



其中
 446                 int numFiles = MemoryMappedFile::flushAll( true ); 
调用的是基类的flushAll  :

148     /*static*/ int MongoFile::flushAll( bool sync ) {                                                             
149         notifyPreFlush();          // 为空,还没有干什么事
150         int x = _flushAll(sync);                                                                                                                                                                                                         
151         notifyPostFlush();       // 目前为空
152         return x;                                                                                                 

153     }   


-->

155     /*static*/ int MongoFile::_flushAll( bool sync ) {
156         if ( ! sync ) {
157             int num = 0;
158             LockMongoFilesShared lk;
159             for ( set<MongoFile*>::iterator i = mmfiles.begin(); i != mmfiles.end(); i++ ) {
160                 num++;
161                 MongoFile * mmf = *i;
162                 if ( ! mmf )
163                     continue;
164 
165                 mmf->flush( sync );
166             }
167             return num;
168         }
169 
170         // want to do it sync
171         set<MongoFile*> seen;//集合存放已经被flush过的 MF 
172         while ( true ) {
173             auto_ptr<Flushable> f;
174             LockMongoFilesShared lk;
175             for ( set<MongoFile*>::iterator i = mmfiles.begin(); i != mmfiles.end(); i++ ) {
176                 MongoFile * mmf = *i;
177                 if ( ! mmf )
178                     continue;
179                 if ( seen.count( mmf ) ) 
180                     continue;
181                 f.reset( mmf->prepareFlush() ); // 准备flush
182                 seen.insert( mmf );
183                 break;
184             }
185             if ( ! f.get() )
186                 break;
187 
188             f->flush(); // 准备flush  // 执行flush
189         }
190         return seen.size();
191     }             

这里面的for循环和while一起在用感觉有点多余,也许只需要一个for循环就行了,不知道为什么还要在外面加上一层while。  目前的时间复杂度就是O(n ^ 2) 了.

LockMongoFilesShared lk;
这里加锁,应该是为了防止其它插入的修改。 有待验证。 

prepareFlush  为纯虚函数,在子类的实现是在  ./util/mmap_posix.cpp  :

215     MemoryMappedFile::Flushable * MemoryMappedFile::prepareFlush() {                                                                                                                                                                     
216         return new PosixFlushable( viewForFlushing() , fd , len );
217     }
218 

148         virtual void* viewForFlushing() { 
149             if( views.size() == 0 )
150                 return 0;
151             verify( views.size() == 1 );
152             return views[0];
153         }
看样子,只取views[0] 了。    views是MemoryMappedFile 的private变量,之后我们去分析views是怎么来的?  为什么只认定为views.size为1的时候取出views[0]?

197     class PosixFlushable : public MemoryMappedFile::Flushable {
198     public:
199         PosixFlushable( void * view , HANDLE fd , long len )
200             : _view( view ) , _fd( fd ) , _len(len) {
201         }                                                                                                                                                                                                                                
202 
203         void flush() {
204             if ( _view && _fd )
205                 if ( msync(_view, _len, MS_SYNC ) )
206                     problem() << "msync " << errnoWithDescription() << endl;
207 
208         }
209 
210         void * _view;
211         HANDLE _fd;
212         long _len;
213     };

在f->flush()  就调用了上面的 系统函数msync (内存同步文件)。

http://linux.die.net/man/3/msync           http://hi.baidu.com/xwp007/item/9a6caed4492a4ee3b3f777f9

<think>我们正在尝试安装MongoDB的特定版本5.0.2。在Ubuntu系统中,MongoDB提供了自己的仓库,我们可以通过添加该仓库并指定版本进行安装。 步骤如下: 1. 导入MongoDB的GPG密钥 2. 为MongoDB创建一个list文件(在/etc/apt/sources.list.d/目录下) 3. 更新本地包数据库 4. 安装指定版本的MongoDB包 但是,注意:MongoDB的版本号在包名中通常只包含主版本和次版本(如5.0),而不会包含修订版本(如5.0.2)。实际上,安装时我们指定主次版本,然后通过更新来获取最新的修订版本。但我们可以指定安装5.0.2版本,如果该版本在仓库中存在的话。 然而,通常情况下,我们安装的是5.0版本,然后系统会自动安装该系列的最新修订版(包括5.0.2)。但如果我们必须确保安装的是5.0.2,那么我们需要明确指定每个组件的版本号。 根据MongoDB的安装文档,我们可以这样安装指定版本: 首先,添加MongoDB的仓库。这里我们使用Ubuntu 20.04(focal)作为例子,如果你使用的是其他版本,请替换`focal`为相应的代号。 步骤: 1. 导入公钥 wget -qO - https://www.mongodb.org/static/pgp/server-5.0.asc | sudo apt-key add - 2. 创建list文件 echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/5.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-5.0.list 3. 更新包列表 sudo apt update 4. 安装指定版本:我们可以使用以下命令安装特定版本(例如5.0.2): sudo apt install mongodb-org=5.0.2 mongodb-org-database=5.0.2 mongodb-org-server=5.0.2 mongodb-org-shell=5.0.2 mongodb-org-mongos=5.0.2 mongodb-org-tools=5.0.2 注意:每个组件都需要单独指定版本号,并且版本号必须完全匹配。 但是,请注意:在安装时,可能会遇到依赖问题,因为每个组件的依赖可能要求相同的版本。因此,我们通常将所有的组件都指定为相同的版本。 另外,为了防止自动更新(因为MongoDB建议手动升级),我们可以将MongoDB的包标记为保留,这样就不会在系统更新时自动升级了: sudo apt-mark hold mongodb-org mongodb-org-database mongodb-org-server mongodb-org-shell mongodb-org-mongos mongodb-org-tools 因此,完整的命令序列如下: 注意:请确保你使用的Ubuntu版本与MongoDB仓库支持的版本一致。这里以Ubuntu 20.04 (focal)为例。 如果系统不是focal,请替换为正确的代号(如Ubuntu 18.04是bionic,Ubuntu 22.04是jammy)。但请注意,MongoDB 5.0支持Ubuntu 20.04和18.04,不支持22.04(因为5.0发布时22.04还未发布)。如果使用22.04,可能需要使用其他方法。 下面给出完整的命令:</think>要在 Ubuntu 上安装 MongoDB 5.0.2 的特定版本,需要执行以下步骤: ### 完整安装步骤: ```bash # 1. 导入 MongoDB 公钥 wget -qO - https://www.mongodb.org/static/pgp/server-5.0.asc | sudo apt-key add - # 2. 创建 MongoDB 5.0 的源列表文件 echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu $(lsb_release -cs)/mongodb-org/5.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-5.0.list # 3. 更新软件包索引 sudo apt update # 4. 安装指定版本 (5.0.2) sudo apt install -y \ mongodb-org=5.0.2 \ mongodb-org-database=5.0.2 \ mongodb-org-server=5.0.2 \ mongodb-org-shell=5.0.2 \ mongodb-org-mongos=5.0.2 \ mongodb-org-tools=5.0.2 # 5. 防止自动更新 sudo apt-mark hold mongodb-org* ``` ### 关键点解释: 1. **版本锁定**: - 使用 `=` 指定确切版本号(`5.0.2`) - 必须为所有组件指定相同版本 2. **apt-mark hold**: - 防止系统自动更新 MongoDB - 保持版本固定在 5.0.2 3. **版本兼容性**: - MongoDB 5.0 支持 Ubuntu 18.04/20.04/22.04 - `$(lsb_release -cs)` 自动获取当前系统代号 ### 验证安装: ```bash # 查看安装版本 mongod --version # 应显示:db version v5.0.2 # 启动服务 sudo systemctl start mongod # 检查运行状态 sudo systemctl status mongod ``` ### 常见问题处理: 1. **依赖错误**: ```bash # 先尝试修复依赖 sudo apt --fix-broken install # 清除无效包 sudo apt autoclean ``` 2. **版本不可用**: - 确保源地址正确:`https://repo.mongodb.org/apt/ubuntu` - 检查[官方安装文档](https://www.mongodb.com/docs/manual/tutorial/install-mongodb-on-ubuntu/) 3. **升级现有版本**: ```bash # 先卸载旧版 sudo apt purge mongodb-org* sudo rm -r /var/log/mongodb /var/lib/mongodb ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值