1. 程式人生 > >MongoDB是什麼?看完你就知道了

MongoDB是什麼?看完你就知道了

最近在回顧mongodb的相關知識,輸出一篇文章做為MongoDB知識點的總結。
總結的目的在於回顧MongoDB的相關知識點,明確MongoDB在企業級應用中充當的角色,為之後的技術選型提供一個可查閱的資訊簡報

一、概述

1.MongoDB是什麼?用一句話總結

MongoDB是一款為web應用程式和網際網路基礎設施設計的資料庫管理系統。沒錯MongoDB就是資料庫,是NoSQL型別的資料庫

2.為什麼要使用MongoDB?

(1)MongoDB提出的是文件、集合的概念,使用BSON(類JSON)作為其資料模型結構,其結構是面向物件的而不是二維表,儲存一個使用者在MongoDB中是這樣子的。

{
    username:'123',
    password:'123'

使用這樣的資料模型,使得MongoDB能在生產環境中提供高讀寫的能力,吞吐量較於mysql等SQL資料庫大大增強。

(2)易伸縮,自動故障轉移。易伸縮指的是提供了分片能力,能對資料集進行分片,資料的儲存壓力分攤給多臺伺服器。自動故障轉移是副本集的概念,MongoDB能檢測主節點是否存活,當失活時能自動提升從節點為主節點,達到故障轉移。

(3)資料模型因為是面向物件的,所以可以表示豐富的、有層級的資料結構,比如部落格系統中能把“評論”直接懟到“文章“的文件中,而不必像myqsl一樣建立三張表來描述這樣的關係。

3.主要特性

(1)文件資料型別
SQL型別的資料庫是正規化的,可以通過主鍵或者外來鍵的約束保證資料的完整性與唯一性,所以SQL型別的資料庫常用於對資料完整性較高的系統。MongoDB在這一方面是不如SQL型別的資料庫,且MongoDB沒有固定的Schema,正因為MongoDB少了一些這樣的約束條件,可以讓資料的儲存資料結構更靈活,儲存速度更加快。

(2)即時查詢能力
MongoDB保留了關係型資料庫即時查詢的能力,保留了索引(底層是基於B tree)的能力。這一點汲取了關係型資料庫的優點,相比於同類型的NoSQL redis 並沒有上述的能力。

(3)複製能力
MongoDB自身提供了副本集能將資料分佈在多臺機器上實現冗餘,目的是可以提供自動故障轉移、擴充套件讀能力。

(4)速度與永續性
MongoDB的驅動實現一個寫入語義 fire and forget ,即通過驅動呼叫寫入時,可以立即得到返回得到成功的結果(即使是報錯),這樣讓寫入的速度更加快,當然會有一定的不安全性,完全依賴網路。
MongoDB提供了Journaling日誌的概念,實際上像mysql的bin-log日誌,當需要插入的時候會先往日誌裡面寫入記錄,再完成實際的資料操作,這樣如果出現停電,程序突然中斷的情況,可以保障資料不會錯誤,可以通過修復功能讀取Journaling日誌進行修復。

(5)資料擴充套件
MongoDB使用分片技術對資料進行擴充套件,MongoDB能自動分片、自動轉移分片裡面的資料塊,讓每一個伺服器裡面儲存的資料都是一樣大小。

4.C/S服務模型

MongoDB核心伺服器主要是通過mongod程式啟動的,而且在啟動時不需對MongoDB使用的記憶體進行配置,因為其設計哲學是記憶體管理最好是交給作業系統,缺少記憶體配置是MongoDB的設計亮點,另外,還可通過mongos路由伺服器使用分片功能。

MongoDB的主要客戶端是可以互動的js shell 通過mongo啟動,使用js shell能使用js直接與MongoDB進行交流,像使用sql語句查詢mysql資料一樣使用js語法查詢MongoDB的資料,另外還提供了各種語言的驅動包,方便各種語言的接入。

5.完善的命令列工具

mongodump和mongorestore,備份和恢復資料庫的標準工具。輸出BSON格式,遷移資料庫。

mongoexport和mongoimport,用來匯入匯出JSON、CSV和TSV資料,資料需要支援多格式時有用。mongoimport還能用與大資料集的初始匯入,但是在匯入前順便還要注意一下,為了能充分利用好mongoDB通常需要對資料模型做一些調整。

mongosniff,網路嗅探工具,用來觀察傳送到資料庫的操作。基本就是把網路上傳輸的BSON轉換為易於人們閱讀的shell語句。

因此,可以總結得到,MongoDB結合鍵值儲存和關係資料庫的最好特性。因為簡單,所以資料極快,而且相對容易伸縮還提供複雜查詢機制的資料庫。MongoDB需要跑在64位的伺服器上面,且最好單獨部署,因為是資料庫,所以也需要對其進行熱備、冷備處理。

二、進入MongoDB shell

因為本篇文章不是API手冊,所有這裡對shell的使用也是基礎的介紹什麼功能可以用什麼語句,主要是為了展示使用MongoDB shell的方便性,如果需要知道具體的MongoDB shell語法可以查閱官方文件。

1.切換資料庫

use dba

建立資料庫並不是必須的操作,資料庫與集合只有在第一次插入文件時才會被建立,與對資料的動態處理方式是一致的。簡化並加速開發過程,而且有利於動態分配名稱空間。如果擔心資料庫或集合被意外建立,可以開啟嚴格模式

2.插入語法

db.users.insert({username:"smith"})
db.users.save({username:"smith"})

區別
若新增的資料中存在主鍵 ,insert() 會提示錯誤,而save() 則更改原來的內容為新內容。

如:
已存在資料: {_id : 1, ” name ” : ” n1 ” },再次進行插入操作時,
insert({_id : 1, ” name ” : ” n2 ” }) 會報主鍵重複的錯誤提示
save({ _id : 1, ” name ” : ” n2 ” }) 會把 n1 修改為 n2 。
相同點:
若新增的資料中沒有主鍵時,會增加一條記錄。
已存在資料: { _id : 1, ” name ” : ” n1 ” },再次進行插入操作時,
insert({ ” name ” : ” n2 ” }) 插入的資料因為沒有主鍵,所以會增加一條資料
save({ ” name ” : ” n2 ” }) 增加一條資料。

3.查詢語法

db.users.find()
db.users.count()

4.更新語法

db.users.update({username:"smith"},{$set:{country:"Canada"}})
//把使用者名稱為smith的使用者的國家改成Canada

db.users.update({username:"smith"},{$unset:{country:1}})
//把使用者名稱為smith的使用者的國家欄位給移除

db.users.update({username:"jones"},{$set:{favorites:{movies:["casablance","rocky"]}}})
//這裡主要體現多值修改,在favorties欄位中新增多個值

db.users.update({"favorites.movies":"casablance"},{$addToSet:{favorites.movies:"the maltese"}},false,true)
//多項更新

5.刪除語法

db.foo.remove() //刪除所有資料
db.foo.remove({favorties.cities:"cheyene"}) //根據條件進行刪除
db.drop() //刪除整個集合

6.索引相關語法

db.numbers.ensureIndex({num:1})
//建立一個升序索引
db.numbers.getIndexes()
//獲取全部索引

7.基本管理語法

show dbs
//查詢所有資料庫
show collections
//顯示所有表
db.stats()
//顯示資料庫狀態資訊
db.numbers.stats()
//顯示集合表狀態資訊
db,shutdownServer()
//停止資料庫
db.help()
//獲取資料庫操作命令
db.foo.help()
//獲取表操作命令
tab 鍵 //能自動幫我們補全命令

以上的命令只是簡單例項,假設如果你之前沒有學習過任何資料庫語法,同時開始學sql查詢語法和MongoDB 查詢語法,你會發現哪一個更簡單呢?如果你使用的是java驅動去操作MongoDB,你會發現任何的查詢都像Hibernate提供出來的查詢方式一樣,只要構建好一個查詢條件物件,便能輕鬆查詢(接下來會給出示例),博主之前熟悉ES6,所以入手MongoDB js shell完成沒問題,也正因為這樣簡潔,完善的查詢機制,深深的愛上了MongoDB。

三、使用java驅動

使用java驅動連結MongoDB是一件非常簡單的事情,簡單的引用,簡單的做增刪改查。在使用完java驅動後我才發現spring 對MongoDB 的封裝還不如官方自身提供出來的東西好用,下面簡單的展示一下使用。

1.使用maven引入jar包

這裡引用的是最新的驅動包,提供了一套新的訪問連線方式

        <dependency>
            <groupId>org.mongodb</groupId>
            <artifactId>mongodb-driver-sync</artifactId>
            <version>3.8.0-beta3</version>
        </dependency>

2.建立一個訪問客戶端

MongoClient client = MongoClients.create(“mongodb://10.201.76.94:27017”);

3.獲取集合數量

public long count() {
        MongoClient client = this.getClient();
        MongoCollection<Document> collections= client.getDatabase("mongodb_db_name").getCollection("mongodb_collection_name");
        return collections.count();
    }

4.查詢集合

public List<Document> find(Document params,Bson sort,int skip,int limit) {
        MongoClient client = this.getClient();
        MongoCollection<Document> collections= client.getDatabase("mongodb_db_name").getCollection("mongodb_collection_name");
        List<Document> list = new ArrayList<Document>(Integer.valueOf(config.getPro("sync_limit")));
    collections.find(params).sort(sort).skip(skip).limit(limit).forEach(new Block<Document>() {
            @Override
            public void apply(Document document) {
                list.add(document);
            }
        });
        return list;
    }

這裡只舉例了簡單的連結與簡單的MongoDB操作,可見其操作的容易性。使用驅動時是基於TCP套接字與MongoDB進行通訊的,如果查詢結果較多,恰好無法全部放進第一伺服器中,將會向伺服器傳送一個getmore指令獲取下一批查詢結果。

插入資料到伺服器時間,不會等待伺服器的響應,驅動會假設寫入是成功的,實際是使用客戶端生成物件id,但是該行為可以通過配置配置,可以通過安全模式開啟,安全模式可以校驗伺服器端插入的錯誤。

四、schema 設計原則

1.需要關注MongoDB的自身的特性

要清楚瞭解MongoDB的基本資料單元。在關係型資料庫中有帶列和行的資料表。而MongoDB資料的基本單元是BSON文件,在鍵值中有指向不定型別值的鍵,MongoDB擁有即時查詢,但不支援聯結操作,簡單的鍵值儲存只能根據單個鍵來獲取值,不支援事務,但支援多種原子更新操作。

2.需要關注系統本身的讀寫特性

如讀寫比是怎樣的,需要何種查詢,資料是如何更新的,會不會存在什麼併發問題,資料結構化的程度是要求高還是低。系統本身的需求決定mysql還是MongoDB

3.關注MongoDB schema 的設計模式

(1)內嵌與引用
當子物件總是出現在父物件的上下文中時,使用內嵌文件;否則將子物件單獨存一個集合

(2)一對多的關係
在“多”的集合關係中新增id指向依賴的id

(3)多對多
在其中一種對應關係中使用物件陣列指向另外一個物件

(4)樹
具化路徑,在樹中的每個節點都包含一個path欄位,該欄位具體儲存了每個節點祖先的id

(5)動態屬性
可以為不同的動態屬性新增索引,如果需要將屬性圈在一個範圍,那麼可以通過key-value的方式,然後在統一的key上面加索引

(6)關於事務
如果需要事務支援,那麼只能選擇另一種資料庫,或者提供補償性事務來解決事務的問題

在關於schema 的設計中要注意一些原則,比如

  • 不能建立沒用的索引
  • 不能在同一個欄位中存不同的型別
  • 不能把多類實體都放在一個集合裡 不能建立體積大、巢狀深的文件
  • 不能過多的建立集合,集合、索引、資料庫的名稱空間都是有限的
  • 不能建立無法分片的集合

4.關注MongoDB裡面一些具體細節

(1)關注資料庫的概念
資料庫是集合的邏輯與物理分組,MongoDB沒有提供建立資料庫的語法,只有在插入集合時,資料庫才開始建立。建立資料庫後會在磁碟分配一組資料檔案,所有集合、索引和資料庫的其他元資料都儲存在這些檔案中,查閱資料庫使用磁碟狀態可通過

db.stats()

(2)關注集合概念
集合是結構上或概念上相似得文件的容器,集合的名稱可以包含數字、字母或 . 符號,但必須以字母或數字開頭,完全。
限定集合名不能超過128個字元,實際上 . 符號在集合中很有用,能提供某種虛擬名稱空間,這是一種組織上的原則,和其他集合是一視同仁的。在集合中可以使用。

system.namespaces //查詢當前資料庫中定義的所有名稱空間
system.indexes //儲存當前資料庫的所有索引定義

(3)關注文件
其次是鍵值,在MongoDB裡面所有的字串都是UTF-8型別。數字型別包括double、int、long。日期型別都是UTC格式,所以在MongoDB裡面看到的時間會比北京時間慢8小時。整個文件大小會限制在16m以內,因為這樣可以防止建立難看的資料型別,且小文件可以提升效能,批量插入文件理想數字範圍是10~200,大小不能超過16MB。

五、索引與查詢優化

1.索引的經驗法則

(1)索引能顯著減少獲取文件的所需工作量,具體的對比可以通過

.explain()

方法進行對比

(2)解析查詢時MongoDB通過最優計劃選擇一個索引進行查詢,當沒有最適合索引時,會先不同的使用各個索引進行查詢,最終選出一個最優索引做查詢

(3)如果有一個a-b的複合索引,那麼僅針對a的索引是冗餘的

(4)複合索引裡的鍵的順序是很重要的

2.索引型別

(1)單鍵索引
(2)複合索引
(3)唯一性索引
(4)稀疏索引
如索引的欄位會出現null的值,或是大量文件都不包含被索引的鍵

3.索引的構建問題

如果資料集很大時,構建索引將會花費很長的時間,且會影響程式效能,可通過

db.currentOp() //檢視索引的構建時間

當使用 mongorestore 時會重新構建索引。當曾經執行過大規模的刪除時,可使用

 db.values.reIndex() 

對索引進行壓縮,重建

4.識別慢查詢

(1)查閱慢查詢日誌

grep -E '([0-9])+ms' mongod.log //使用grep 命令 識別命令資訊

db.setProfillingLevel(2) //使用解刨器,將記錄每次的讀寫到日誌

db.setProfillingLevel(1) //只記錄慢(100ms)操作

(2)分析慢查詢

db.values.find({}).sort({close:-1}).limit(1).explain()
  • scanOrder 欄位表明沒有使用索引
  • cursor當沒有索引時,用的是BasicCursor,當使用索引時使用的是BtreeCursor
  • n 表示需要返回的結果集
  • nscanned表示需要遍歷的文件數 indexBounds 表示索引邊界

注意新版本的MongoDB 的explain方法是需要引數的,不然只顯示普通的資訊

六、MongoDB副本集

本節同樣主要簡單呈現MongoDB副本集搭建的簡易性,與副本集的強壯性,監控容易性

1.為什麼要使用副本集

提供主從複製能力,熱備能力,故障轉移能力

2.構建方式

rs.initiate()
rs.add("localhost:40001")
rs.add("localhost:40002",{arbiterOnly:true})

3.監控

db.isMasrter()
rs.status()

4.副本集的工作原理

實際上MongoDB對副本集的操作跟mysql主從操作是差不多的,先看一下mysql的主從資料流動過程

主binlog -> 從relay.log -> 從bin.log -> 從資料庫

而MongoDB主要依賴的日誌檔案是oplog

主oplog -> 從oplog

寫操作先被記錄下來,新增到主節點的oplog裡。與此同時,所有從結點複製oplog。首先,檢視自己oplog裡最後一條的時間戳;其次,查詢主節點oplog裡所有大於此時間戳的條目;最後,把那些條目新增到自己的oplog裡並應用到自己的庫裡。從節點使用長輪詢立即應用來自主結點oplog的新條目。

當遇到以下情況,從節點會停止複製

  • 如果從節點在主節點的oplog裡找不到它所同步的點,那麼會永久停止複製
  • 一旦某個從節點沒能 在主節點的oplog裡找到它已經同步的點,就無法再保證這個從結點的完美副本

local資料庫儲存了所有副本集元素據和oplog日誌

  • replset.minvalid 包含指定副本整合員的初始化同步資訊
  • system.replset 儲存在副本集配置文件
  • system.indexes 標準索引說明容器
  • me slaves 主要用於寫關注

可以使用以下命令檢視複製情況

db.oplog.rs.findOne()
  • ts 儲存了該條目的BSON時間戳
  • t 是從紀元開始的描述
  • i是計數器
  • op 表示操作碼
  • ns 標明瞭有關的名稱空間

5.心跳檢測

每個副本整合員每秒鐘ping一次其他所有成員,可以通過rs.status()看到節點上次的心跳檢測時間戳和健康狀況。

6.故障轉移

這個點沒必要過多描述,但是有一個特殊場景,如果從節點和仲裁節點都被殺了,只剩下主節點,他會把自己降級成為從節點。

7.提交與回滾

如果主節點的資料還沒有寫到從庫,那麼資料不能算提交,當該主節點變成從節點時,便會觸發回滾,那些沒寫到從庫的資料將會被刪除,可以通過rollback子目錄中的BSON檔案恢復回滾的內容。

8.驅動與複製

(1)使用單節點連結
只能連結到主節點,如果連結到從節點的話,會被拒絕寫入操作,但是如果沒有使用安全模式,因為mongo的fire and forget 特性,會把拒絕寫入的異常給吃掉。

(2)使用副本集方式連結
能根據寫入的情況自動進行故障轉移,但是當副本集進行新的選舉時,還是會出現故障,如果不使用安全模式,依舊會出現寫不進去,但現實成功的情況。

(3)寫關注
可以使用寫關注來關注資料是否已經被寫入MongoDB的庫中,使用寫關注會消耗效能,需要在速度和永續性之間做出權衡。

七、分片

分片是資料庫切分的一個概念實現,這裡也是簡單總結為什麼要使用分片以及分片的原理,操作。

1.為什麼需要分片

當資料量過大,索引和工作資料集佔用的記憶體就會越來越多,所以需要通過分片負載來解決這個問題

2.分片的工作原理

(1)分片元件

  • 分片:每個分片都是一個副本集
  • mongos路由器:是一個路由器,將讀寫請求指引到合適的分片上
  • 配置伺服器config:持久化分片叢集的元資料,包括:全域性叢集配置;每個資料庫、集合和特定範圍資料位置;一份變更記錄,儲存了資料在分片之間進行遷移的歷史資訊。配置伺服器之間不是副本集形式存在,mongos向配置伺服器提交資訊時是兩階段提交,保證配置伺服器之間的一致性。

(2)分片的核心操作
分片一個集合:分片是根據一個屬性的範圍進行劃分的,MongoDB使用所謂的分片鍵讓每個文件在這些範圍裡找到自己的位置

塊:是位於一個分片中的一段連續的分片鍵範圍,可以理解為若干個塊組成分片,分片組成MongoDB的全部資料

(3)拆分與遷移
塊的拆分:初始化時只有一個塊,達到最大塊尺寸64MB或100000個文件就會觸發塊的拆分。把原來的範圍一分為二,這樣就有了兩個塊,每個塊都有相同數量的文件。

遷移:當分片中的資料大小不一時會產生遷移的動作,比如分片A的資料比較多,會將分片A裡面的一些塊轉移到分片B裡面去。分片叢集通過在分片中移動塊來實現均衡,是由名為均衡器的軟體程序管理的,任務是確保資料在各個分片中保持均勻分佈,當叢集中擁有塊最多的分片與擁有塊最少分片的塊差大於8時,均衡器就會發起一次均衡處理。

3.分片實戰

啟動兩個副本集、三個配置伺服器、一個mongos程序

配置分片

sh.help() //檢視分片相關幫助
sh.addShard() //新增分片
db,getSiblingDB("config").shards.find() //檢視分片列表
sh.status() //分片詳情
sh.enableSharding("cloud-docs") //開啟一個數據庫上的分片
db.getSiblingDB("config").databases,find() //檢視資料庫列表
sh.shardCollection("cloud-docs.spreadsheets",{username:1,_id:1}) //使用一個分片鍵定義一個分片集合spreadsheets,根據使用者名稱進行切分
sh.getSiiblingDB("config").collections.findOne() //檢視集合列表
db.chunks.count() //檢視塊的個數
db.chunks.findOne() //檢視塊的資訊
db.changelog.count(}what:"split"|) //檢視塊切分日誌
db.changelog.find({what:"moveChunk.commit"}).count() //檢視日誌遷移記錄

4.分片的查詢與索引

(1)分片查詢型別

  • 針對性查詢:查詢包含分片鍵
  • 全域性查詢或分散/聚集查:查詢不包含分片鍵
  • 查詢過程:通過分片鍵將查詢路由給指定分片,一旦到了某個分片上,由分片自行決定使用哪個索引來執行該查詢

(2)索引
每個分片都維護了自己的索引,當在分片集合上宣告索引時,每個分片都會為它那部分集合構建獨立的索引,每個分片上的分片集合都應該擁有相同的索引。

分片集合只允許在_id欄位和分片鍵上新增唯一性索引,其他地方不行,因為這需要在分片間進行通訊,實施起來很複雜。

當建立分片時,會根據分片鍵建立一個索引。

5.選擇分片鍵

(1)分片鍵是不可修改的、分片鍵的選擇非常重要
(2)低效的分片鍵

  • 分佈性差:如使用BSON物件ID,那麼會導致所有最新插入的文件都會落到某個很小的連續範圍,無法分散插入
  • 缺乏區域性性:升序分片鍵有明確的方向,完全隨機的分片鍵則根本沒有方向。前者無法分散插入,後者插入分散,如使用MD5作為分片鍵

(3)理想的分片鍵

  • 將插入資料均勻分佈到各個分片上
  • 保證CRUD操作能夠利用區域性性 有足夠的粒度進行塊拆分
  • 滿足這些要求的分片鍵通常由兩個欄位組成,第一個是粗粒度的,第二個粒度較細

6.生產環境中的分片

(1)部署拓撲

  • 複製mongod:需要獨立的部署伺服器
  • 配置伺服器:配置伺服器不需要有自己的機器

根據不同的資料中心劃分
這裡寫圖片描述

(2)最低要求

  • 副本集每個成員,無論是完整的副本集節點還是仲裁節點,都需要放在不同的機器上 每個用於複製的副本整合員都需要有自己的機器
  • 副本集仲裁節點很輕量級,和其他程序共用一臺機器即可
  • 配置伺服器也可以選擇與其他程序共用一臺機器

這裡寫圖片描述

(3)配置的注意事項
需要估計叢集大小,可使用以下命令對現有集合進行分片處理

sh.splitAt("cloud-docs.spreadsheets",{"username":"chen","_id":ObjectId("")})
//手動拆分塊
sh.moveChunk("cloud-docs.spreadsheets",{username:"chen"},"shardB")
//手動將某分塊移至分片B
db.runCommand({removeshard:"shard-1/arete:30100,arete:30101"}) 
//刪除分片
db.runCommand({moveprimary:"test",to:"shard-0-test-rs"});
//移動主分片

(4)備份分片叢集
備份分片時需要停止均衡器

db.settings.update({_id:"ba;ancer"},{$set:{stopped:true},true});
sh.setBalancerState(false);
//停止均衡器,此時均衡器將進行最後一輪均衡

db.locks.find({_id:"balancer"});
sh.isBalancerRunning();
//檢視均衡器狀態,任何狀態大於0 的狀態值都說明均衡器仍在進行中

八、部署與管理

1.部署

(1)部署架構
使用64位機器、32位機器會制約mongodb的記憶體,使其最大值為1.5GB

(2)cpu
mongodb 只有當索引和工作集都可放入記憶體時,才會遇到CPU瓶頸,CPU在mongodb使用中的作用是用來檢索資料,如果看到CPU使用飽和的情況,可以通過查詢慢查詢日誌,排查是不是查詢的問題導致的,如果是可以通過新增索引來解決問題
mongodb寫入資料時會使用到CPU,但是mongodb寫入時間一次只用到一個核,如果有頻繁的寫入行為,可以通過分片來解決這個問題

(3)記憶體
大記憶體是mongodb的保障,如果工作集大小超過記憶體,將會導致效能下降,因為這將會增加資料載入入記憶體的動作

(4)硬碟
mongodb預設每60s會與磁碟強制同步一次,稱為後臺重新整理,會產生I/O操作。在重啟時mongodb會將磁盤裡面的資料載入至記憶體,高速磁碟將會減少同步的時間

(5)檔案系統
使用ext4 和 xfs 檔案系統
禁用最後訪問時間

vim /etc/fstab

(6)檔案描述符
linux 預設檔案描述符是1024,需要大額度的提升這個額度

(7)時鐘
mongodb各個節點伺服器之間使用ntp伺服器

2.安全

(1)繫結IP
啟動時使用 - -bind_ip 命令

(2)身份驗證
啟動時使用 - -auth 命令

db.addUser("","",true)
//建立使用者,最後一個引數指定是否只讀

(3)副本集身份認證
使用keyFile,注意keyFile檔案的許可權必須是600,不然會啟動不起來

3.資料的匯入與匯出

mongoimport
mongoexport

4.伺服器配置

(1)拓撲結構
搭建副本集至少需要兩個節點,其中仲裁結點不需要有自己的伺服器

(2)Journaling日誌
寫資料時會先寫入日誌,而此時的資料也不是直接寫入硬碟,而是寫入記憶體
但是Journaling日誌會消耗記憶體,所以可以在主庫上面關閉,在從庫上面啟動
可以單獨為Journaling日誌使用一塊固態硬碟
在插入時,可以通過驅動確保Journaling插入後再反饋,但是會非常影響效能

5.日誌

logpath 選項指定日誌儲存地址
-vvvvv 選項(v越多,輸出越詳細)
db.runCommand({logrotare:1}) 開啟滾動日誌

6.資料庫監控命令

(1)serverStatus
這裡寫圖片描述
globalLock 表示伺服器花在寫鎖上面的總時間
mem顯示瞭如何使用記憶體
bits 表明這臺機器的位長
resident 表示佔用實體記憶體數量
virtual 表示使用的虛擬記憶體

(2)top
這裡寫圖片描述

(3)db.currentOp()
這裡寫圖片描述

7.mongostat

動態展示mongodb活動資料

8.web控制檯

佔用當前mongodb監聽埠往上1000號的埠

9.備份與恢復

(1)mongodump
把資料庫內容匯出成BSON檔案,而mongorestore能讀取並還原這些檔案

(2)mongorestore
把匯出的BSON檔案還原到資料庫

(3)備份原始資料檔案
可以這麼做,但是,操作之前需要進行鎖庫處理 db.runCommand({fsync:1,lock:true})
db.$cmd.sys.unlock.findOne() 請求解鎖操作,但是資料庫不會立刻解鎖,需要使用db.currentOp()驗證

10.壓緊與修復

(1)修復
mongd –repair 修復所有資料庫
db.runCommand({repairDatabase:1}) 修復單個數據庫
修復就是根據Jourling檔案讀取和重寫所有資料檔案並重建各個索引

(2)壓緊

db.spreadsheets.reIndex() //重建索引
db.runCommand({compact:"spreadsheets"}) 

壓緊,會重寫資料檔案,並重建集合的全部索引,需要停機或者在從庫上面執行,如果需要在主庫上面執行,需要新增force引數 保證加寫鎖

11.效能調優

(1)監控磁碟狀態

iostat

(2)為提升效能檢查索引和查詢
總的來說,掃描儘可能少的文件
保證沒有冗餘的索引,冗餘的索引會佔用磁碟空間、消耗更多的記憶體,在每次寫入時還需做更多工作

(3)新增記憶體

db.stats() //檢視資料庫資料佔用大小狀態

dataSize 資料大小 和 indexSize 索引大小,如果兩者的和大於記憶體,那麼將會影響效能
storageSize超過dataSize 資料大小 兩倍以上,就會因磁碟碎片而影響效能,需要壓縮