zoukankan      html  css  js  c++  java
  • MongoDB-3.2 oplog删除策略优化

    MongoDB oplog是一个capped collection,创建capped collection时,createCollection可以设置size(最大字节数)和max(最大文档数)的参数,当这个集合的『总大小超过size』或者『总文档数超过max』时,在新插入文档时就会自动删除一些集合内最先插入的文档,相当于一片环形的存储空间。

    oplog(local.oplog.rs集合)默认情况下配置为可用磁盘空间的5%,当oplog写满时,就会开始删除最先写入的oplog,一次正常的insert操作包含如下步骤:

    1. 将文档写入指定的集合
    2. 将写入操作记录到oplog
    3. 如果oplog满了,删除最先写入的oplog

    优化策略

    MongoDB 3.2为了提升写入性能,使用wiredtiger引擎时,针对local.oplog.rs这个集合的删除策略进行了优化,主要改进:

    1. 将删除动作从用户的写入路径移除,放到后台线程执行
    2. 批量删除,并不是oplog一满就立马触发删除,而是一次删除一批

    实施方案

    monogd启动时,会根据oplog的最大字节数将整个集合分为10-100个Stone(可以理解为oplog的一段数据,包含多个文档,Stone的具体个数oplogSizeMB的配置相关)。

    
    WiredTigerRecordStore::OplogStones::OplogStones(OperationContext* txn, WiredTigerRecordStore* rs)
        : _rs(rs) {
        //...
        unsigned long long maxSize = rs->cappedMaxSize();
    
        const unsigned long long kMinStonesToKeep = 10ULL;
        const unsigned long long kMaxStonesToKeep = 100ULL;
    
        unsigned long long numStones = maxSize / BSONObjMaxInternalSize;
        _numStonesToKeep = std::min(kMaxStonesToKeep, std::max(kMinStonesToKeep, numStones));
        _minBytesPerStone = maxSize / _numStonesToKeep;
        // ...
    }
    

    其中_numStonesToKeep为oplog应该保持的Stone个数,而_minBytesPerStone代表每个Stone的最小字节数。

    接下来,会根据oplog当前的大小以及_minBytesPerStone来估算下,当前的oplog大致包含的Stone数量,并通过采样的方式来获取每个Stone的起始位置(不能保证每个Stone的大小跟预期完全一样),然后将所有的Stone按顺序存储到一个队列中。

    mongod在服务写请求的过程中,每次都会记录下新产生oplog的大小,当新产生的oplog的总量超过_minBytesPerStones时,就会产生一个新的Stone加入到队列中。

    void WiredTigerRecordStore::OplogStones::createNewStoneIfNeeded(RecordId lastRecord) {
    
        if (_currentBytes.load() < _minBytesPerStone) {
            // Must have raced to create a new stone, someone else already triggered it.
            return;
        }
    
        // ...
            
        OplogStones::Stone stone = {_currentRecords.swap(0), _currentBytes.swap(0), lastRecord};
        _stones.push_back(stone);
    
        _pokeReclaimThreadIfNeeded(); // 唤醒后台回收oplog空间的线程
    }
    

    当队列中的Stone数量超过_numStonesToKeep,后台线程就会删除最老的Stone里的数据,来回收oplog的存储空间。

    参考资料

    转载自:https://yq.aliyun.com/articles/50138

  • 相关阅读:
    枚举进程中打开的句柄
    DuplicateHandle进程间句柄复制
    64位CreateProcess逆向:(二)0环下参数的整合即创建进程的整体流程
    通过SOCKS代理渗透整个内网
    为什么NtReadVirtualMemory 硬件断点无法下断
    在EXE和DLL中,FindResource的区别
    (转) MyBatis(1)——快速入门
    C# if为false仍然进入方法体,==和qeual结果不一致
    InstallShield卸载不彻底,残留大量dll文件
    WPF System.InvalidCastException: 无法将类型为“System.Windows.Media.Color”的对象强制转换为类型“System.Windows.Media.Brush”。
  • 原文地址:https://www.cnblogs.com/xibuhaohao/p/11303230.html
Copyright © 2011-2022 走看看