MongoDB主庫和從庫的數據大小不一致原因判斷


1. 環境(MongoDB的版本是3.2.16)

 

[root@xxx-mongodb-primary ~]# cat /etc/redhat-release 
CentOS Linux release 7.4.1708 (Core) 
[root@xxx-mongodb-primary ~]# getenforce 
Disabled
[root@xxx-mongodb-primary ~]# systemctl is-active firewalld.service 
unknown
[root@xxx-mongodb-primary ~]# systemctl is-enabled firewalld.service 
disabled

 

2. 從庫恢復

由於某種原因需要恢復MongoDB復制集的從庫,使用了一主一從一ab的結構,主從配置文件是一致的,我本次恢復從庫使用的官網的初始同步更新的辦法(https://docs.mongodb.com/manual/tutorial/restore-replica-set-from-backup/#shut-down-the-mongod-instance-that-you-restored):

1. 停止從庫后,從主庫移除從庫節點
2. 從庫刪除dbpath下的所有文件
3. 啟動從庫
4. 主庫加入從庫節點,復制開始

主庫配置文件

 

[root@xxx-mongodb-primary conf]# cat mongo.conf 
systemLog:
  destination: file
  path: /mongodb/27017/log/mongodb.log
  logAppend: true
storage:
  journal:
    enabled: true
  dbPath: /mongodb/27017/data
  directoryPerDB: true
  #engine: wiredTiger
  wiredTiger:
    engineConfig:
      cacheSizeGB: 5
      directoryForIndexes: true
    collectionConfig:
      blockCompressor: zlib
    indexConfig:
      prefixCompression: true
processManagement:
  fork: true
net:
  port: 27017
  bindIp: 0.0.0.0
replication:
  oplogSizeMB: 4096
  replSetName: my_repl
security:
  authorization: enabled
  keyFile: /mongodb/27017/conf/keyfile

 

3. 發現主從庫數據顯示大小不一致

但是主從完成同步后,發現從庫顯示的prd_market_history庫的數據的大小和主庫相差了1G左右(主庫數據才4G大小),但是使用mongodump備份出來的數據的文件大小幾乎一致,都是3.6GB,只相差十多K。

備份MongoDB庫的命令:mongodump   -uroot -pxxx --port 27017 --authenticationDatabase admin -d prd_market_history -o /mongodb/backup/

主庫信息:

 

從庫信息:

 

4. 原因

https://segmentfault.com/q/1010000015112464?tdsourcetag=s_pcqq_aiomsg

題外話,MongoDB歷史上出現過master/slave復制(其實現在也還存在)。嚴格地說,主備通常指的是那個東西。而我們現在用的基本上是復制集(replica set)。

再說你這種情況,其實是正常的。原理跟你的磁盤用久了會有碎片是一個道理。特別是你曾經大規模刪除過數據的情況下。簡單地解釋下,假設你的表中有doc1/doc2/doc3/doc4一共4個文檔,在磁盤上的存儲順序是:
doc1|doc2|doc3|doc4
現在你刪除了doc2,磁盤上的空間使用情況變成:
doc1|(空白)|doc3|doc4
系統是沒有辦法釋放這個空白空間的,除非你進行磁盤整理,把空白空間移到最后:
doc1|doc3|doc4|(空白)
然后系統才可以截斷文件尾部的空白,釋放掉這個空間。可以看出來,要把空白移動到文件尾是個相當費時費力的操作,最簡單的辦法是:把后面所有的文檔順序前移來填補doc2留下的空白(如上所示doc3/doc4被前移)。但是這樣涉及到大量的磁盤I/O,會對性能造成嚴重影響。當然不乏其他整理磁盤碎片的方法,但是無論哪一個,都會造成比較嚴重的I/O影響,因此一般我們是不會進行這樣的整理的。進行碎片整理的方式就是:compact命令。如前所述,因為它會對性能造成嚴重的影響,因此一般只會在維護時間進行這個操作。而就算你不進行這個操作,系統也知道哪些地方是空白的,在有新文檔進來的時候,會嘗試重新使用這些空白的部分從而最大化空間利用率。只是,無論再好的算法,空間重復利用一定不可能是100%的,因為新進來的文檔永遠沒有辦法正好跟之前被刪除的文檔一樣大,所以只能找一個比新文檔更大的空間來利用,這樣就會留下一個更小的、更難重復利用的碎片。
另外一種變通的方案是把節點內容刪除,重新進行一次同步。因為同步時相當於把所有文檔全部抓取一遍,並一個接一個重新寫到磁盤上,因此同步完成之后文檔在磁盤上是緊湊排列的,相當於進行了碎片整理。而且在這個過程中,受影響的是從節點,它在同步過程中並不對外提供服務,所以對線上的影響是最小的。但是注意,它同樣會對主節點造成影響,因為它要把主節點上的全部數據都讀一遍,主節點I/O升高是無法避免的。

為什么從節點比主節點小,上面已經很清楚的說明了。


免責聲明!

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



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