mongodb的oplog日志


##########################################################################

oplog不及binlog:

首先,來一個綜述,比較mongodb的oplog和mysql的binlog,oplog不如binlog,比如設置一個延遲節點的時間,由於oplog是一個固定大小的集合,延遲時間設置大了,就會無法同步數據,而mysql的binlog可以設置binlog過期時間,根本不用擔心。

 
        

任何一種數據庫都有各種各樣的日志,MongoDB也不例外。MongoDB中有4種日志,分別是系統日志、Journal日志、oplog主從日志、慢查詢日志等。這些日志記錄着MongoDB數據庫不同方面的蹤跡。下面分別介紹這幾種日志。

系統日志

系統日志在MongoDB數據庫中很重要,它記錄着MongoDB啟動和停止的操作,以及服務器在運行過程中發生的任何異常信息。

配置系統日志的方法比較簡單,在啟動mongod時指定logpath參數即可

mongod -logpath=/data/log/mongodb/serverlog.log -logappend 復制代碼

系統日志會向logpath指定的文件持續追加。

Journal日志

journaling(日記) 日志功能則是 MongoDB 里面非常重要的一個功能 , 它保證了數據庫服務器在意外斷電 、 自然災害等情況下數據的完整性。它通過預寫式的redo日志為MongoDB增加了額外的可靠性保障。開啟該功能時,MongoDB會在進行寫入時建立一條Journal日志,其中包含了此次寫入操作具體更改的磁盤地址和字節。因此一旦服務器突然停機,可在啟動時對日記進行重放,從而重新執行那些停機前沒能夠刷新到磁盤的寫入操作。

MongoDB配置WiredTiger引擎使用內存緩沖區來保存journal記錄,WiredTiger根據以下間隔或條件將緩沖的日志記錄同步到磁盤

  1. 從MongoDB 3.2版本開始每隔50ms將緩沖的journal數據同步到磁盤
  2. 如果寫入操作設置了j:true,則WiredTiger強制同步日志文件
  3. 由於MongoDB使用的journal文件大小限制為100MB,因此WiredTiger大約每100MB數據創建一個新的日志文件。當WiredTiger創建新的journal文件時,WiredTiger會同步以前journal文件

MongoDB達到上面的提交,便會將更新操作寫入日志。這意味着MongoDB會批量地提交更改,即每次寫入不會立即刷新到磁盤。不過在默認設置下,系統發生崩潰時,不可能丟失超過50ms的寫入數據。

數據文件默認每60秒刷新到磁盤一次,因此Journal文件只需記錄約60s的寫入數據。日志系統為此預先分配了若干個空文件,這些文件存放在/data/db/journal目錄中,目錄名為_j.0、_j.1等 長時間運行MongoDB后,日志目錄中會出現類似_j.6217、_j.6218的文件,這些是當前的日志文件,文件中的數值會隨着MongoDB運行時間的增長而增大。數據庫正常關閉后,日記文件會被清除(因為正常關閉后就不在需要這些文件了).

向mongodb中寫入數據是先寫入內存,然后每隔60s在刷盤,同樣寫入journal,也是先寫入對應的buffer,然后每隔50ms在刷盤到磁盤的journal文件 使用WiredTiger,即使沒有journal功能,MongoDB也可以從最后一個檢查點(checkpoint,可以想成鏡像)恢復;但是,要恢復在上一個檢查點之后所做的更改,還是需要使用Journal

如發生系統崩潰或使用kill -9命令強制終止數據庫的運行,mongod會在啟動時重放journal文件,同時會顯示出大量的校驗信息。

上面說的都是針對WiredTiger引擎,對於MMAPv1引擎來說有一點不一樣,首先它是每100ms進行刷盤,其次它是通過private view寫入journal文件,通過shared view寫入數據文件。這里就不過多講解了,因為MongoDB 4.0已經不推薦使用這個存儲引擎了。 從MongoDB 3.2版本開始WiredTiger是MongoDB推薦的默認存儲引擎

需要注意的是如果客戶端的寫入速度超過了日記的刷新速度,mongod則會限制寫入操作,直到日記完成磁盤的寫入。這是mongod會限制寫入的唯一情況。

固定集合(Capped Collection)

在講下面兩種日志之前先來認識下capped collection。

MongoDB中的普通集合是動態創建的,而且可以自動增長以容納更多的數據。MongoDB中還有另一種不同類型的集合,叫做固定集合。固定集合需要事先創建好,而且它的大小是固定的。固定集合的行為類型與循環隊列一樣。如果沒有空間了,最老的文檔會被刪除以釋放空間,新插入的文檔會占據這塊空間。

創建固定集合:

db.createCollection("collectionName",{"capped":true, "size":100000, "max":100}) 復制代碼

創建了一個大小為100000字節的固定大小集合,文檔數量為100.不管先到達哪個限制,之后插入的新文檔就會把最老的文檔擠出集合:固定集合的文檔數量不能超過文檔數量限制,也不能超過大小限制。

固定集合創建之后就不能改變,無法將固定集合轉換為非固定集合,但是可以將常規集合轉換為固定集合。

db.runCommand({"convertToCapped": "test", "size" : 10000}); 復制代碼

固定集合可以進行一種特殊的排序,稱為自然排序(natural sort),自然排序返回結果集中文檔的順序就是文檔在磁盤的順序。自然順序就是文檔的插入順序,因此自然排序得到的文檔是從舊到新排列的。當然也可以按照從新到舊:

db.my_capped_collection.find().sort({"$natural": -1}); 復制代碼

oplog主從日志

Replica Sets復制集用於在多台服務器之間備份數據。MongoDB的復制功能是使用操作日志oplog實現的,操作日志包含了主節點的每一次寫操作。oplog是主節點的local數據庫中的一個固定集合。備份節點通過查詢這個集合就可以知道需要進行復制的操作。

一個mongod實例中的所有數據庫都使用同一個oplog,也就是所有數據庫的操作日志(插入,刪除,修改)都會記錄到oplog中

每個備份節點都維護着自己的oplog,記錄着每一次從主節點復制數據的操作。這樣,每個成員都可以作為同步源給其他成員使用。 如圖所示,備份節點從當前使用的同步源中獲取需要執行的操作,然后在自己的數據集上執行這些操作,最后再將這些操作寫入自己的oplog,如果遇到某個操作失敗的情況(只有當同步源的數據損壞或者數據與主節點不一致時才可能發生),那么備份節點就會停止從當前的同步源復制數據。

 

oplog-copy.png

 

oplog中按順序保存着所有執行過的寫操作,replica sets中每個成員都維護者一份自己的oplog,每個成員的oplog都應該跟主節點的oplog完全一致(可能會有一些延遲)

如果某個備份節點由於某些原因掛了,但它重新啟動后,就會自動從oplog中最后一個操作開始進行同步。由於復制操作的過程是想復制數據在寫入oplog,所以備份節點可能會在已經同步過的數據上再次執行復制操作。MongoDB在設計之初就考慮到了這種情況:將oplog中的同一個操作執行多次,與只執行一次的效果是一樣的。

由於oplog大小是固定的,它只能保持特定數量的操作日志。通常,oplog使用空間的增長速度與系統處理寫請求的速率幾乎相同:如果主節點上每分鍾處理了1KB的寫入請求,那么oplog很可能也會在一分鍾內寫入1KB條操作日志。

但是,有一些例外:如果單次請求能夠影響到多個文檔(比如刪除多個文檔或者多文檔更新),oplog中就會出現多條操作日志。如果單個操作會影響多個文檔,那么每個受影響的文檔都會對應oplog的一條日志。因此,如果執行db.student.remove()刪除了10w個文檔,那么oplog中也就會有10w條操作日志,每個日志對應一個被刪除的文檔。如果執行大量的批量操作,oplog很快就會被填滿。

慢查詢日志

MongoDB中使用系統分析器(system profiler)來查找耗時過長的操作。系統分析器記錄固定集合system.profile中的操作,並提供大量有關耗時過長的操作信息,但相應的mongod的整體性能也會有所下降。因此我們一般定期打開分析器來獲取信息。

默認情況下,系統分析器處於關閉狀態,不會進行任何記錄。可以在shell中運行db.setProfilingLevel()開啟分析器

db.setProfilingLevel(level,<slowms>) 0=off 1=slow 2=all
復制代碼

第一個參數是指定級別,不同的級別代表不同的意義,0表示關閉,1表示默認記錄耗時大於100毫秒的操作,2表示記錄所有操作。第二個參數則是自定義“耗時過長"標准,比如記錄所有耗時操作500ms的操作

db.setProfilingLevel(1,500);
復制代碼

如果開啟了分析器而system.profile集合並不存在,MongoDB會為其建立一個大小為若干MB的固定集合(capped collection)。如希望分析器運行更長時間,可能需要更大的空間記錄更多的操作。此時可以關閉分析器,刪除並重新建立一個新的名為system.profile的固定集合,並令其容量符合要求。然后在數據庫上重新啟用分析器。

可以通過db.system.profile.stats()查看集合的最大容量.


作者:think123
鏈接:https://juejin.im/post/6844903907169140750
來源:掘金
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。

 

 

動態更改oplog大小:

 

db.adminCommand({replSetResizeOplog:1, size: 16384})

 

 

 

 獲取最舊的一個操作:

 

glc-test:PRIMARY> use local
switched to db local
glc-test:PRIMARY> db.oplog.rs.find().sort({$natural: -1}).pretty().limit(1)
{
        "ts" : Timestamp(1605170004, 1),
        "t" : NumberLong(115),
        "h" : NumberLong("-8786076471049145979"),
        "v" : 2,
        "op" : "n",
        "ns" : "",
        "wall" : ISODate("2020-11-12T08:33:24.005Z"),
        "o" : {
                "msg" : "periodic noop"
        }
}
glc-test:PRIMARY> 

 

 

 獲取最新的一個操作:

 

glc-test:PRIMARY> use local
switched to db local
glc-test:PRIMARY> db.oplog.rs.find().sort({$natural: 1}).pretty().limit(1)
{
        "ts" : Timestamp(1604648269, 8897),
        "t" : NumberLong(113),
        "h" : NumberLong("-8471504986882691135"),
        "v" : 2,
        "op" : "i",
        "ns" : "eagle.content_v1",
        "ui" : UUID("02ddbc0a-e76b-450e-ae38-bd5eb220c773"),
        "wall" : ISODate("2020-11-06T07:37:49.312Z"),
        "o" : {
                "_id" : "1478dong",
                "uid" : "",
                "lv3" : "",
                "lv4" : "",
                "lv5" : "",
                "comment_id" : "1478",
                "creation_time" : "2020-10-22 17:11:14",
                "content" : "內容",
                "skuid" : "77",
                "xxname" : "藍牙",
                "score" : "5",
                "name" : "xxx",
                "rate" : "0.99",
                "general_rate" : "0.003",
                "poor_rate" : "0.007",
                "poorcount" : "242",
                "general_count" : "132",
                "good" : "5759",
                "comment" : "10165",
                "fetchtime" : "2020-10-23 01:17:57",
                "first" : "數碼",
                "second" : "影",
                "third" : "音",
                "source" : "jingdong",
                "sub_comment" : [
                        "內容"
                ],
                "sub_comment_sa" : [
                        0,
                        0
                ],
                "sub_comment_entity" : [
                        [
                                "功能"
                        ]
                ],
                "sub_tags3" : [ ],
                "sub_tags4" : [
                        [ ]
                ],
                "su" : "箱",
                "tem_id" : "1004",
                "sa_origin" : "",
                "sa" : "0",
                "category" : "狗狗",
                "pms_id" : "",
                "source_comment_id" : "",
                "update_time" : NumberLong("1603405763132")
        }
}
glc-test:PRIMARY> 

 

 oplog的時間滑動窗口范圍就是兩者之間的時間ts差值:

 

glc-test:PRIMARY> db.oplog.rs.find({},{ts:1}).sort({$natural: 1}).pretty().limit(1)
{ "ts" : Timestamp(1604648269, 8897) }
glc-test:PRIMARY> db.oplog.rs.find({},{ts:1}).sort({$natural: -1}).pretty().limit(1)
{ "ts" : Timestamp(1605171394, 1) }
glc-test:PRIMARY> 

 

 

 oplog的動態擴容與縮容:(mongodb版本至少3.6以上)

 

mivpn:PRIMARY> db.getReplicationInfo()
{
        "logSizeMB" : 65536,
        "usedMB" : 3061.23,
        "timeDiff" : 769648,
        "timeDiffHours" : 213.79,
        "tFirst" : "Wed Jan 20 2021 12:22:17 GMT+0800 (CST)",
        "tLast" : "Fri Jan 29 2021 10:09:45 GMT+0800 (CST)",
        "now" : "Fri Jan 29 2021 10:09:46 GMT+0800 (CST)"
}
mivpn:PRIMARY> db.adminCommand({replSetResizeOplog:1,size:102400})
{
        "ok" : 1,
        "operationTime" : Timestamp(1611886191, 79),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1611886191, 79),
                "signature" : {
                        "hash" : BinData(0,"OUP6mdMfsdZU/YM98XDnlhdXlzg="),
                        "keyId" : NumberLong("6919692836459773955")
                }
        }
}
mivpn:PRIMARY> db.getReplicationInfo()
{
        "logSizeMB" : 102400,
        "usedMB" : 3061.24,
        "timeDiff" : 769654,
        "timeDiffHours" : 213.79,
        "tFirst" : "Wed Jan 20 2021 12:22:17 GMT+0800 (CST)",
        "tLast" : "Fri Jan 29 2021 10:09:51 GMT+0800 (CST)",
        "now" : "Fri Jan 29 2021 10:09:58 GMT+0800 (CST)"
}
mivpn:PRIMARY> 

 

 回收空間:

use local;
db.runCommand({ "compact" : "oplog.rs" });

 

 

 oplog文件大小:local.oplog.rs對應的物理文件是壓縮文件:1/3

 

glc:PRIMARY> db.getReplicationInfo()
{
        "logSizeMB" : 900000,
        "usedMB" : 892698.48,
        "timeDiff" : 213954,
        "timeDiffHours" : 59.43,
        "tFirst" : "Wed Jan 27 2021 05:09:20 GMT+0800 (CST)",
        "tLast" : "Fri Jan 29 2021 16:35:14 GMT+0800 (CST)",
        "now" : "Fri Jan 29 2021 16:35:14 GMT+0800 (CST)"
}

 

 

[work@xxx collection]$ ll -h
total 304G
-rw------- 1 work work  32K Nov 30 15:02 0-979332807111034247.wt
-rw------- 1 work work 304G Jan 29 16:38 14-979332807111034247.wt
-rw------- 1 work work  32K Dec 15 12:24 17-979332807111034247.wt
-rw------- 1 work work  36K Nov 30 15:02 19-979332807111034247.wt
-rw------- 1 work work  16K Dec 15 12:24 2-979332807111034247.wt
-rw------- 1 work work 320K Jan 29 15:30 40-979332807111034247.wt
-rw------- 1 work work  36K Jun 30  2020 4-979332807111034247.wt
-rw------- 1 work work  16K Dec 15 12:24 6-979332807111034247.wt
-rw------- 1 work work  16K Dec  3 16:31 8-979332807111034247.wt

 

 

 

 

####################################################


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM