標籤:
瞭解應用的動態
1. 瞭解進行中的操作:db.currentOp() , 可以加過濾條件,從而只顯示合格結果。
1). 尋找有問題的操作:db.currentOp() 最常見的操作就是用來尋找速度較慢的操作
2). 終止操作的執行:將該操作的opid作為參數,執行db.killOp()來終止該操作的執行。並非所有操作都能被終止。一般來講,只有交出了鎖的進程才能被終止。
3). 假象:在尋找哪些操作耗時過長時,可能會發現一些長時間啟動並執行內部操作。所有local.oplog.rs中長時間啟動並執行請求,以及所有回寫監聽命令,都可以被忽略掉。
4). 避免幽靈操作:阻止幽靈寫入的最好方式是使用應答式寫入,即每次寫入操作都會等待上一次寫入操作完成後才進行下去。
2. 使用系統分析器:可以利用系統分析器來尋找耗時過長的操作。系統分析器會記錄特殊集合system.profile中的操作,但會導致整體效能下降,所以應該只在需要時候開啟。
可在shell中運行db.setProfilingLevel()來開啟分析器:db.setProfilingLevel(2) 層級為2,意味著"分析器會記錄所有內容",效能損失大。
可將分析器層級設定為1,即只顯示長耗時的操作。層級為1預設記錄耗時大於100ms的操作。也可以自訂"耗時過長"的標準,把耗時值作為函數的第二個參數。db.setProfilingLevel(1,500)
將分析層級設為0可關閉分析器。通常情況下,不要將耗時值slows的值設定的過小。即使分析器處於關閉狀態,slowns也會對mongod有所影響,因為它決定了哪些操作將作為耗時過長操作
被記錄到日誌中。
3. 計算空間消耗:
1). 文檔:使用Object.bsonsize()函數:Object.bsonsize({_id:ObjectId()}) Object.bsonsize(db.users.findOne())
2). 集合:stats函數可用來顯示一個集合的資訊:db.boards.stats()
3). 資料庫:db.stats() 在一個繁忙的系統上列出資料庫資訊會非常慢,而且會阻礙其他動作,應避免此類操作。
4. 使用mongotop和mongostat
1). mongotop類似於UNIX中的top工具,可以概述那個集合最為繁忙。通過運行mongotop-locks ,從而得知每個資料庫的狀態。
2). mongostat 提供伺服器的資訊。mongostat預設每秒輸出一次包含目前狀態的列表,可在命令列中傳入參數更改時間間隔。每個欄位都會給出自上一次被輸出以來,所對應的活動發生次數。
3). 想要獲得資料庫中進行中的操作快照,mongostat是很好的選擇,但如果要對資料庫進行長期監控昂,類似MMS的工具可能更為適合。
資料管理
1. 配置身分識別驗證
1). 身分識別驗證基本原理:admin(管理員)和local(本地)是兩個特殊的資料庫,他們當中的使用者可對任何資料庫進行操作。這兩個資料庫中的使用者可被看做是超級使用者。經認證後,管理使用者可對任何資料庫
進行讀寫,同時能執行某些只有管理員才能執行的命令,如listDatabases和shutdown。
在shell中用addUser建立使用者時,經第三個參數readOnly設定為true,即可建立一個唯讀許可權使用者。
2). 配置身分識別驗證:啟用身分識別驗證後,用戶端必須登入才能進行讀寫。然而,在MongoDB中有一點值得注意:在admin資料庫中建立使用者前,伺服器上的"本地"用戶端可對資料庫進行讀寫。
一般情況下正常建立管理使用者進行身分識別驗證即可避免上的問題,但分區例外,因為資料庫admin會被儲存到設定管理員上。可以將網路設定為只允許用戶端訪問mongos進程即可,或者在分區添加管理員賬戶。
3). 身分識別驗證的工作原理:資料庫中的使用者是作為文檔被儲存在器system.users集合中的。這種用以儲存使用者資訊的文檔結構是{user:username,readOnly:true,pwd:password hash} 。其中password hash
是基於username和密碼產生的散列值。
2. 建立和刪除索引:建立和刪除索引是資料庫最耗費資源的操作之一,所以應小心地安排建立索引
1). 在獨立伺服器上建立索引:db.foo.ensureIndex({"somefield":1},{"background":true})
2). 在複本集上建立索引:
3). 在分區叢集上建立索引:在分區叢集上建立索引,與在複本集中建立索引的步驟相同,不過需要在每個分區上分布建立一次。首先,關閉均衡器,然後按照 複本集建立索引的步驟,依次在每個分區中進行操作,
即把每個分區當做一個單獨的複本集。最後,通過mongos運行ensureIndex,並重啟均衡器。
只有在現存分區中添加索引時才需要這樣做,新的分區會在開始接收集合資料區塊時抓取集合的索引。
4). 刪除索引:使用dropIndexes命令並制定索引名來刪除索引:db.runCommand({"dropIndexes":foo,"index":"alphabet"}) 。索引名為“*”時會刪除一個集合上的所有索引,但這種方法無法刪除"_id"索引。
只有刪除整個集合才能刪除掉該索引。刪除集合中的全部文檔不會對索引產生影響,新文檔插入後索引仍可正常增加。
5). 注意記憶體溢出殺手(OOM Killer):Linux的記憶體溢出殺手負責終止使用過多記憶體的進程。考慮到MongoDB使用記憶體的方式,除了在建立索引的情況下,它通常不會遇到這種問題。如果在建立索引時,mongod突然消失,請檢查
/var/log/messages檔案,其中記錄了OOM Killer 的輸出資訊。在後台建立索引或增加交換空間可避免此類情況。如果有機器的慣例許可權,可以將MongoDB設定為不可被OOM Killer終止。
3. 預熱資料:
1). 將資料庫移至記憶體:如果需要將資料庫移至記憶體中,可使用UNIX中的dd工具,從而在啟動mongod前載入資料檔案。將/data/db/brains.*替換為/data/db/*可將真箇資料目錄載入記憶體。如將一個或一組資料庫載入
記憶體,需占的記憶體又要比實際記憶體大的話,則其中一些資料會立即被清除出記憶體。
mongod 啟動時,會向作業系統請求資料檔案。如果作業系統發現記憶體中已經存在了這些資料檔案,就可以立即訪問mongod。
2). 將集合移至記憶體:MongoDB提供了touch命令來預熱資料。啟動mongod(也許在另一個連接埠,或關閉防火牆對它的限制),對一個集合使用touch命令,從而將其載入記憶體:
db.runCommand({"touch":"logs","data":true,"index":true}) 將logs集合中的所有文檔和索引載入記憶體。可以指定值載入文檔或只載入索引。注意記憶體的使用方式。
3). 自訂預熱:
a. 載入一個特定的索引
b. 載入最新動向文檔
c. 記載最近建立的文檔:利用最近建立文檔的時間戳記進行文檔查詢。ObjectId中包含時間戳記。
d. 重放應用使用記錄:MongoDB提供名為診斷記錄的功能來記錄和回放操作流水。啟動診斷記錄會造成效能損失,所以最好通過臨時使用的方式來獲得一份"有代表性的操作流水"
4. 壓縮資料:為消除空區段,並高效重整集合,可使用compact命令:db.runCommand({"compact":"collName"})
壓縮操作會消耗大量資源,不應再mongod向用戶端提供服務時,計劃壓縮操作。推薦做法類似於建立索引的做法,即在每個備份節點中對資料執行壓縮操作,然後關閉主節點,進行最後壓縮操作。
壓縮會將文檔儘可能地安排在一起,文檔間的間隔參數預設為1.如需更大的間隔參數,可使用額外的參數來指定它:db.runCommand({"compact":"collname","paddingFactor":1.5}) ,最大值為4
可以通過repair命令來回收磁碟空間。repair命令會對所有資料進行複製,所以必須擁有和當前資料檔案一樣大小的額空餘磁碟空間。在啟動mongod時使用--repair選項(如需要,還可以使用--repairepath
選項)來進行修複。可以在shell中調用db.repairDatabase()來修複資料庫。
5. 移動集合:
1). 可使用renameCollection命令重新命名集合:db.sourceColl.renameCollection("newname") , 執行這個命令時可以傳入第二個參數,從而決定當名為newname的集合存在時如何處理。true 會
刪除名為newname的集合,false ,會拋出錯誤。
2). 想要在資料庫間移動集合,必須進行轉儲和恢複操作,或手動複製集合中的文檔。
cloneCollection將一個集合移動到另一個不同的mongod中:db.runCommond({"cloneCollection":collName,"from":"hostname":27017})
6. 預分配資料資料檔案:
持久性
1. 如磁碟和軟體正常運行,則MongoDB能夠在系統崩潰或強制關閉後,確保資料的完整性。
2. 日誌系統的用途:MongoDB會在進行寫入時建立一條日誌,日記中包含了此次寫入操作具體更改的磁碟地址和位元組。因此,一旦伺服器突然停機,可以在啟動時對日誌進行重放,從而重新執行
那些停機前沒有能夠重新整理到磁碟的寫入操作。資料檔案預設每60秒重新整理一次,因此記錄檔值需記錄約60秒的寫入內容。日記系統為此預先分配了若干個空間檔案,這些檔案存放在/data/db/journal目錄中,
檔案名稱為_j.0,_j.1等。資料庫正常關閉記錄檔會被清除。如發生崩潰,mongod會在啟動時重放記錄檔,同時顯示出大量的校正資訊。
1). 批量提交寫入操作:MongoDB預設每隔100毫秒,或是寫入資料達到若干MB時,便會將這些操作寫入日記。這意味著MongoDB會成批量地提交更改,即每次寫入不會立即重新整理到磁碟。不過預設設定
下,系統發生崩潰時,最多丟失100毫秒的寫入。可通過向getLastEror傳遞 j 選項,來確保寫入操作的成功。設定此選項後,大約等待30毫秒。對一些重要的資料,可以使用此選項。
2). 設定提交時間間隔:運行setParameter命令,設定journalCommitInterval的值(最小為2毫秒,最大為500毫秒)。無論時間間隔設定為多少,使用帶有"j":true的getLastError命令都會將該值減少到原來的三分之一。
2. 關閉日記系統:如果寫入資料的價值不及寫入速度降低帶來的損失,我們可能會禁用日記系統。如果希望系統崩潰後能繼續工作,有以下幾種方法:
1). 替換資料檔案
2). 修複資料檔案:mongod內建兩種修複工具,一種是mongod內建的,一種是mongodump內建的。mongodump的修複更接近底層。 --repair.
3). mongod.lock 檔案:異常退出時會有mongod.lock檔案,阻礙mongod重新啟動,標誌我們需要先修複資料。也可以通過刪除該檔案重啟mongod(生產環境不建議).
4). 隱形異常退出:
3. MongoDB無法包保證的事項:
1). 檢驗資料損毀:可以使用validate命令,檢驗集合是否有損壞:db.foo.validate()
4. 複本集的持久性:
Mongodb 筆記08