mongodb學(xué)習(xí)之oplog

背景:

創(chuàng)新互聯(lián)建站專注于企業(yè)成都全網(wǎng)營(yíng)銷推廣、網(wǎng)站重做改版、平房網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、成都h5網(wǎng)站建設(shè)、成都做商城網(wǎng)站、集團(tuán)公司官網(wǎng)建設(shè)、成都外貿(mào)網(wǎng)站建設(shè)、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁(yè)設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性價(jià)比高,為平房等各大城市提供網(wǎng)站開(kāi)發(fā)制作服務(wù)。

   原來(lái)一個(gè)同事問(wèn)我主從MongoDB數(shù)據(jù)庫(kù)為什么數(shù)據(jù)差距很大,我讓他察看一下兩邊有啥不一樣,發(fā)現(xiàn)

主的local庫(kù)有13G從卻很小,進(jìn)入local之后du發(fā)現(xiàn)有一個(gè)collection前綴的文件有13g,說(shuō)明是local數(shù)據(jù)庫(kù)中一個(gè)集合太大了,推測(cè)是oplog太大了,oplog是類似于MySQL的binlog oracle的archivelog

當(dāng)Primary進(jìn)行寫操作的時(shí)候,會(huì)將這些寫操作記錄寫入Primary的Oplog 中,而后Secondary會(huì)將Oplog 復(fù)制到本機(jī)并應(yīng)用這些操作,從而實(shí)現(xiàn)Replication的功能。
同時(shí)由于其記錄了Primary上的寫操作,故還能將其用作數(shù)據(jù)恢復(fù)。
可以簡(jiǎn)單的將其視作Mysql中的binlog。

為了進(jìn)一步確認(rèn),進(jìn)入mongodb之后通過(guò)

show dbs 

use local

show collections

看到現(xiàn)有的集合

然后

db.getReplicationInfo()

rs.printReplicationInfo()

了解一下復(fù)制信息以及oplog大小與使用情況

為進(jìn)一步確認(rèn)相應(yīng)的文件是否為oplog

db.printCollectionStats()

根據(jù)展示出來(lái)的結(jié)果只需要知道兩條信息:

"ns" : "local.oplog.$main",

"uri" : "statistics:table:local/collection-2-1716662444632575459"

就可以確認(rèn)oplog集合的相應(yīng)文件,oplog如果太大可以清理和修改大小。

MongoDB oplog是一個(gè)capped collection,創(chuàng)建capped collection時(shí),createCollection可以設(shè)置size(最大字節(jié)數(shù))和max(最大文檔數(shù))的參數(shù),當(dāng)這個(gè)集合的『總大小超過(guò)size』或者『總文檔數(shù)超過(guò)max』時(shí),在新插入文檔時(shí)就會(huì)自動(dòng)刪除一些集合內(nèi)最先插入的文檔,相當(dāng)于一片環(huán)形的存儲(chǔ)空間。

oplog(local.oplog.rs集合)默認(rèn)情況下配置為可用磁盤空間的5%,當(dāng)oplog寫滿時(shí),就會(huì)開(kāi)始刪除最先寫入的oplog,一次正常的insert操作包含如下步驟:

  1. 將文檔寫入指定的集合

  2. 將寫入操作記錄到oplog

  3. 如果oplog滿了,刪除最先寫入的oplog

優(yōu)化策略

MongoDB 3.2為了提升寫入性能,使用wiredtiger引擎時(shí),針對(duì)local.oplog.rs這個(gè)集合的刪除策略進(jìn)行了優(yōu)化,主要改進(jìn):

  1. 將刪除動(dòng)作從用戶的寫入路徑移除,放到后臺(tái)線程執(zhí)行

  2. 批量刪除,并不是oplog一滿就立馬觸發(fā)刪除,而是一次刪除一批

實(shí)施方案

monogd啟動(dòng)時(shí),會(huì)根據(jù)oplog的最大字節(jié)數(shù)將整個(gè)集合分為10-100個(gè)Stone(可以理解為oplog的一段數(shù)據(jù),包含多個(gè)文檔,Stone的具體個(gè)數(shù)oplogSizeMB的配置相關(guān))。

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應(yīng)該保持的Stone個(gè)數(shù),而_minBytesPerStone代表每個(gè)Stone的最小字節(jié)數(shù)。

mongodb 學(xué)習(xí)之oplog

接下來(lái),會(huì)根據(jù)oplog當(dāng)前的大小以及_minBytesPerStone來(lái)估算下,當(dāng)前的oplog大致包含的Stone數(shù)量,并通過(guò)采樣的方式來(lái)獲取每個(gè)Stone的起始位置(不能保證每個(gè)Stone的大小跟預(yù)期完全一樣),然后將所有的Stone按順序存儲(chǔ)到一個(gè)隊(duì)列中。

mongod在服務(wù)寫請(qǐng)求的過(guò)程中,每次都會(huì)記錄下新產(chǎn)生oplog的大小,當(dāng)新產(chǎn)生的oplog的總量超過(guò)_minBytesPerStones時(shí),就會(huì)產(chǎn)生一個(gè)新的Stone加入到隊(duì)列中。

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(); // 喚醒后臺(tái)回收oplog空間的線程
}

當(dāng)隊(duì)列中的Stone數(shù)量超過(guò)_numStonesToKeep,后臺(tái)線程就會(huì)刪除最老的Stone里的數(shù)據(jù),來(lái)回收oplog的存儲(chǔ)空間。

修改mongodb oplog size

oplog簡(jiǎn)介:

oplog:operations log的簡(jiǎn)寫,存儲(chǔ)在一個(gè)特殊的數(shù)據(jù)庫(kù)中(local),oplog就存儲(chǔ)在其中的oplog.$main集合里面,這個(gè)集合是一個(gè)固定集合,新操作會(huì)自動(dòng)替換舊的操作,以保證oplog不會(huì)超過(guò)預(yù)設(shè)的大小,其中的每個(gè)文檔都代表主節(jié)點(diǎn)上執(zhí)行的一個(gè)操作,oplog會(huì)包含所有對(duì)數(shù)據(jù)有修改的的操作(查詢操作不會(huì)記錄),默認(rèn)下,oplog大小會(huì)占用64位的實(shí)例5%的可用磁盤空間。
mongo復(fù)制的過(guò)程:主節(jié)點(diǎn)應(yīng)用業(yè)務(wù)操作修改到數(shù)據(jù)庫(kù)中,然后記錄這些操作到oplog中,從節(jié)點(diǎn)復(fù)制這些oplog,然后應(yīng)用這些修改。ps:這些操作是異步的。如果從節(jié)點(diǎn)的操作已經(jīng)被主節(jié)點(diǎn)落下很遠(yuǎn),oplog日志在從節(jié)點(diǎn)還沒(méi)執(zhí)行完,oplog可能已經(jīng)輪滾一圈了,從節(jié)點(diǎn)跟不上同步,復(fù)制就會(huì)停下,從節(jié)點(diǎn)需要重新做完整的同步,為了避免此種情況,盡量保證主節(jié)點(diǎn)的oplog足夠大,能夠存放相當(dāng)長(zhǎng)時(shí)間的操作記錄。

查詢oplog的大小及保存的操作記錄持續(xù)的時(shí)長(zhǎng)

repltest:PRIMARY> db.printReplicationInfo()
configured oplog size:   1024MB
log length start to end: 3705secs (1.03hrs)
oplog first event time:  Thu Oct 10 2013 11:13:29 GMT+0800 (CST)
oplog last event time:   Thu Oct 10 2013 12:15:14 GMT+0800 (CST)
now:                     Fri Oct 11 2013 16:33:42 GMT+0800 (CST)

查詢從節(jié)點(diǎn)的數(shù)據(jù)源列表,其中有數(shù)據(jù)滯后的時(shí)間

repltest:PRIMARY> db.printSlaveReplicationInfo()
source:   192.168.1.101:37017
syncedTo: Fri Oct 11 2013 16:38:16 GMT+0800 (CST)
= 1 secs ago (0hrs)
source:   192.168.1.100:37017
no replication info, yet.  State: ARBITER
so,修改oplog的大小:(下面介紹兩種方式)

方式一:

The oplog exists internally as a capped collection, so you cannot modify its size in the course of normal operations.另:改變oplog大小,需要在每個(gè)節(jié)點(diǎn)上執(zhí)行維護(hù)模式。(官方推薦)
步驟:

1:重啟一個(gè)實(shí)例以單機(jī)模式,

通常再關(guān)閉server之前,使用rs.stepDown() 強(qiáng)制primary成為secondary

2:重新創(chuàng)建一個(gè)新大小,

其中包含舊的oplgo的入口條目的oplog

3:重啟mongod作為replica set的成員

操作步驟:
1>: Restart a Secondary in Standalone Mode on a Different Port
關(guān)閉mongod實(shí)例:
repset:PRIMARY> use admin
repset:PRIMARY> db.shutdownServer()
重啟mongod實(shí)例以單機(jī)模式,修改端口,并不要加--replSet參數(shù)
#vim /etc/mongo.conf
  dbpath=/var/lib/mongodb
  logpath=/var/log/mongodb/mongo.log
  pidfilepath=/var/run/mongo.pid
  directoryperdb=true
  logappend=true
  #replSet=repset
  bind_ip=192.168.1.100,127.0.0.1
  port=37017
  oplogSize=2000
  fork=true# mongod -f /etc/mongo.conf
備份oplog# mongodump --db local --collection 'oplog.rs' --port 37017
2>: Recreate the Oplog with a New Size and a Seed Entry
保存oplog的最新的時(shí)間點(diǎn)
> use local
> db.temp.save( db.oplog.rs.find( { }, { ts: 1, h: 1 } ).sort( {$natural : -1} ).limit(1).next() )
> db.temp.find()
刪除舊的oplog
> db.oplog.rs.drop()
3> :Create a New Oplog
創(chuàng)建一個(gè)新的Oplog,大小為2G
> db.runCommand( { create: "oplog.rs", capped: true, size: (2 * 1024 * 1024 * 1024) } )
插入前面保存的舊的oplog的時(shí)間點(diǎn)的記錄
> db.oplog.rs.save( db.temp.findOne() )
> db.oplog.rs.find()
4>:Restart the Member:
關(guān)閉單機(jī)實(shí)例:
> use admin
> db.shutdownServer()
修改回配置# vim /etc/mongo.conf
  dbpath=/var/lib/mongodb
  logpath=/var/log/mongodb/mongo.log
  pidfilepath=/var/run/mongo.pid
  directoryperdb=true
  logappend=true
  replSet=repset
  bind_ip=192.168.1.100,127.0.0.1
  port=37017
  oplogSize=2000
  fork=true
啟動(dòng)mongod
# mongod -f /etc/mongo.conf
重復(fù)上述步驟到所有需要更改的節(jié)點(diǎn)。

方式二:

步驟:
1:停掉所有replca set節(jié)點(diǎn).
2:主節(jié)點(diǎn)刪除local庫(kù)下的文件,從節(jié)點(diǎn)刪除數(shù)據(jù)目錄下所有文件.
3:修改所有節(jié)點(diǎn)配置文件.
4:重啟所有節(jié)點(diǎn).
5:重新配置replca set,從節(jié)點(diǎn)會(huì)重新同步所有數(shù)據(jù)(initial sync).
ps:此法好處是簡(jiǎn)單,但需要停掉服務(wù),且如果數(shù)據(jù)量很大,初始同步的成本較高

1>:關(guān)閉mongod實(shí)例(所有節(jié)點(diǎn))

> use admin
> db.shutdownServer()

2>:刪除local數(shù)據(jù)庫(kù)下的所有文件(PRIMARY節(jié)點(diǎn))

# rm -rf /var/lib/mongodb/local/*
  刪除mongo數(shù)據(jù)目錄(其他節(jié)點(diǎn)上操作,可不要?jiǎng)h錯(cuò)哦,建議所有rm操作先mv,待無(wú)問(wèn)題時(shí)候再刪除)# rm -rf /var/lib/mongodb/*

3> 修改所有節(jié)點(diǎn)配置文件(oplogsize)

# vim /etc/mongo.conf
  dbpath=/var/lib/mongodb
  logpath=/var/log/mongodb/mongo.log
  pidfilepath=/var/run/mongo.pid
  directoryperdb=true
  logappend=true
  replSet=repset
  bind_ip=192.168.1.100,127.0.0.1
  port=37017
  oplogSize=2000
  fork=true

4> 重啟所有節(jié)點(diǎn)mongod

> mongod -f /etc/mongo.conf

當(dāng)前題目:mongodb學(xué)習(xí)之oplog
網(wǎng)頁(yè)路徑:http://bm7419.com/article34/jdedpe.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供手機(jī)網(wǎng)站建設(shè)全網(wǎng)營(yíng)銷推廣、外貿(mào)網(wǎng)站建設(shè)、微信公眾號(hào)、商城網(wǎng)站、虛擬主機(jī)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都app開(kāi)發(fā)公司