天天看點

mongoDB進階之副本集

第二章 MongoDB檢視指令

test:登入時預設存在的庫

admin庫:系統預留庫,MongoDB系統管理庫

local庫:本地預留庫,存儲關鍵日志

config庫:MongoDB配置資訊庫

檢視資料庫指令

show databases/show dbs

show tables/show collections

use admin

db/select database()

一:插入指令

1.插入單條

db.user_info.insert({"name":"SATA","age":27,"ad":"北京市朝陽區"})
db.user_info.insert({"name":"HU","age":27,"ad":"北京市朝陽區"})
db.user_info.insert({"name":"GANG","age":28,"ad":"北京市朝陽區"})
db.user_info.insert({"name":"MA","age":28,"ad":"北京市朝陽區"})
db.user_info.insert({"name":"YI","age":28,"ad":"北京市朝陽區","sex":"待定"})           

2.插入多條

db.inventory.insertMany([
    { "item": "journal", "qty": 25, "size": { "h": 14, "w": 21, "uom": "cm" }, "status": "A" },
    { "item": "notebook", "qty": 50, "size": { "h": 8.5, "w": 11, "uom": "in" }, "status": "A" },
    { "item": "paper", "qty": 100, "size": { "h": 8.5, "w": 11, "uom": "in" }, "status": "D" },
    { "item": "planner", "qty": 75, "size": { "h": 22.85, "w": 30, "uom": "cm" }, "status": "D" },
    { "item": "postcard", "qty": 45, "size": { "h": 10, "w": 15.25, "uom": "cm" }, "status": "A" }
]);           

二:mongoDB 查詢指令

1.查詢一條

db.user_info.findOne()           

2.查詢所有

db.user_info.find()           

3.查詢符合條件

db.user_info.find({"age":28})
select * from user_info where age = 28;           

4.查詢嵌套的條件

db.inventory.find( { "size.uom": "in" } )
db.inventory.find( 
    { 
        "size.uom": "in" 
    } 
)

           

5.邏輯查詢:and

db.inventory.find( { "size.uom": "cm" ,"status" : "A"} )
db.inventory.find( 
    { 
        "size.uom": "cm" ,
        "status" : "A"
    } 
)           

6.邏輯查詢 或

db.inventory.find(
    {
        $or:[
                {status:"D"},
                {qty:{$lt:30}
            ]
    }
)           

7.邏輯查詢+或+and+正規表達式

db.inventory.find({status:"A",$or:[{qty:{$lt:30}},{item:/^p/}]})
db.inventory.find( 
    {
        status: "A",
        $or: [ 
                { qty: { $lt: 30 } }, 
                { item: /^p/ } 
             ]
    } 
)

db.inventory.find( 
    {
        status: "A",
        $or: [ 
                { qty: { $gt: 30 } }, 
                { item: /^p/ } 
             ]
    } 
)           

三:mongoDB更新資料

1.更改比對條件的單條資料

db.inventory.find({ "item" : "paper" })

db.inventory.updateOne({ "item" : "paper" },{$set: {  "size.uom" : "cm",  "status" : "P" }})

db.inventory.updateOne(
    { "item" : "paper" },
    {
      $set: {  
                "size.uom" : "cm",  
                "status" : "P" 
            }
    }
)           

2.更改比對條件的多條資料

db.inventory.find({ "qty" : { $lt: 50 } })
db.inventory.updateMany(
    { "qty" : { $lt: 50 } },
    {
       $set: 
            { 
                "size.uom" : "mm", 
                "status": "P" 
            }
    }
)           

3.添加字段

db.user_info.find({ "age" : 27})
db.user_info.updateMany(
    { "age" : 27},
    {
       $set: 
            { 
                "pet" : "cat"
            }
    }
)           

四:mongoDB删除

1.先查找需要删除的資料

db.inventory.find({"status":"P"})           

2.删除單條

db.inventory.deleteOne({"status":"P"})           

3.删除多個

db.inventory.deleteMany({"status":"P"})           

4.删除索引

db.user_info.dropIndex("age_1")           

4.删除集合

show dbs
db 
show tables
db.inventory.drop()           

5.删除庫

show dbs
db 
db.dropDatabase()           

五:mongoDB的索引

1.檢視執行計劃

db.user_info.find({"age":{ $lt: 30 }})
db.user_info.find({"age":{ $lt: 30 }}).explain()           

2.建立索引

db.user_info.createIndex({ age: 1 },{background: true})           

參數說明:

age:1 表示對age字段作為索引的字段,1表示排序規則為升序,-1表示為降序

background 表示放在背景建立,不影響讀寫

3.檢視索引

db.user_info.getIndexes()
           

4.再次檢視執行計劃

db.user_info.find({"age":{ $lt: 30 }}).explain()           

關鍵詞

"stage" : "IXSCAN"
"indexName" : "age_1"           

5.删除索引

db.user_info.dropIndex("age_1")           

索引類型

COLLSCAN - 表示查詢的字段并沒有建立索引,是以查詢的時候會使用全表掃描

IXSCAN – 表示使用索引來找出對應的文檔

六:mongoDB的工具

0.指令介紹

mongod            #啟動指令
mongo            #登入指令         
mongodump           #備份導出,全備壓縮
mongorestore         #恢複
mongoexport           #備份,資料可讀json
mongoimport         #恢複
mongostat        #檢視mongo運作狀态
mongotop        #檢視mongo運作狀态
mongos          #叢集分片指令           

1.mongostat

各字段解釋說明:

insert/s : 官方解釋是每秒插入資料庫的對象數量,如果是slave,則數值前有*,則表示複制集操作

query/s : 每秒的查詢操作次數

update/s : 每秒的更新操作次數

delete/s : 每秒的删除操作次數

getmore/s: 每秒查詢cursor(遊标)時的getmore操作數

command: 每秒執行的指令數,在主從系統中會顯示兩個值(例如 3|0),分表代表 本地|複制 指令

注: 一秒内執行的指令數比如批量插入,隻認為是一條指令(是以意義應該不大)

dirty: 僅僅針對WiredTiger引擎,官網解釋是髒資料位元組的緩存百分比

used: 僅僅針對WiredTiger引擎,官網解釋是正在使用中的緩存百分比

flushes:

For WiredTiger引擎:指checkpoint的觸發次數在一個輪詢間隔期間

For MMAPv1 引擎:每秒執行fsync将資料寫入硬碟的次數

注:一般都是0,間斷性會是1, 通過計算兩個1之間的間隔時間,可以大緻了解多長時間flush一次。flush開銷是很大的,如果頻繁的flush,可能就要找找原因了

vsize: 虛拟記憶體使用量,機關MB (這是 在mongostat 最後一次調用的總資料)

res: 實體記憶體使用量,機關MB (這是 在mongostat 最後一次調用的總資料)

注:這個和你用top看到的一樣, vsize一般不會有大的變動, res會慢慢的上升,如果res經常突然下降,去查查是否有别的程式狂吃記憶體。

qr: 用戶端等待從MongoDB執行個體讀資料的隊列長度

qw:用戶端等待從MongoDB執行個體寫入資料的隊列長度

ar: 執行讀操作的活躍用戶端數量

aw: 執行寫操作的活用戶端數量

注:如果這兩個數值很大,那麼就是DB被堵住了,DB的處理速度不及請求速度。看看是否有開銷很大的慢查詢。如果查詢一切正常,确實是負載很大,就需要加機器了

netIn:MongoDB執行個體的網絡進流量

netOut:MongoDB執行個體的網絡出流量

注:此兩項字段表名網絡帶寬壓力,一般情況下,不會成為瓶頸

conn: 打開連接配接的總數,是qr,qw,ar,aw的總和

注:MongoDB為每一個連接配接建立一個線程,線程的建立與釋放也會有開銷,是以盡量要适當配置連接配接數的啟動參數,maxIncomingConnections,阿裡工程師建議在5000以下,基本滿足多數場景

七:mongoDB的權限和認證

建立使用者和角色

0.與使用者相關的指令

db.auth() 将使用者驗證到資料庫。
db.changeUserPassword() 更改現有使用者的密碼。
db.createUser() 建立一個新使用者。
db.dropUser() 删除單個使用者。
db.dropAllUsers() 删除與資料庫關聯的所有使用者。
db.getUser() 傳回有關指定使用者的資訊。
db.getUsers() 傳回有關與資料庫關聯的所有使用者的資訊。
db.grantRolesToUser() 授予使用者角色及其特權。
db.removeUser() 已過時。從資料庫中删除使用者。
db.revokeRolesFromUser() 從使用者中删除角色。
db.updateUser() 更新使用者資料。           

1.建立管理使用者

mongo db01:27017
use admin
db.createUser(
    {
        user: "admin",
        pwd: "31huiyi.com",
        roles:[
                {
                    role: "root",
                    db:"admin"
                }
              ]
    }
)           

2.檢視建立的使用者

db.getUsers()
           

3.配置檔案添權重限認證參數

security:     
  authorization: enabled           

4.重新開機mongo

mongod -f /opt/mongo_27017/conf/mongodb.conf --shutdown
mongod -f /opt/mongo_27017/conf/mongodb.conf           

5.使用admin使用者登入

mongo db01:27017 -uadmin -p --authenticationDatabase admin           

6.建立其他使用者

use test
db.createUser(
  {
    user: "mysun",
    pwd: "123456",
    roles: [ { role: "readWrite", db: "write" },
             { role: "read", db: "read" } ]
  }
)           

7.建立測試資料

use write
db.write.insert({"name":"zhangya","age":27,"ad":"北京市朝陽區"})
db.write.insert({"name":"zhangya","age":27,"ad":"北京市朝陽區"})
db.write.insert({"name":"yazhang","age":28,"ad":"北京市朝陽區"})
db.write.insert({"name":"xiaozhang","age":28,"ad":"北京市朝陽區"})
db.write.insert({"name":"xiaozhang","age":28,"ad":"北京市朝陽區","sex":"boy"})

use read
db.read.insert({"name":"zhangya","age":27,"ad":"北京市朝陽區"})
db.read.insert({"name":"zhangya","age":27,"ad":"北京市朝陽區"})
db.read.insert({"name":"yazhang","age":28,"ad":"北京市朝陽區"})
db.read.insert({"name":"xiaozhang","age":28,"ad":"北京市朝陽區"})
db.read.insert({"name":"xiaozhang","age":28,"ad":"北京市朝陽區","sex":"boy"})           

8.退出admin,使用mysun使用者登入

mongo db01:27017 -umysun -p --authenticationDatabase test
use write
db.write.find()
db.write.insert({"name":"zhangya","age":27,"ad":"北京市朝陽區"})

use read
db.read.find()
db.read.insert({"name":"zhangya","age":27,"ad":"北京市朝陽區"})           

9.修改使用者權限

use test
db.updateUser(
  'mysun',
  { 
    pwd: "123456",
    roles: [ { role: "readWrite", db: "write" },
             { role: "readWrite", db: "read" } ,
             { role: "readWrite", db: "test" }
             ]
             
  }
)           

10.删除使用者

db.getUsers()
db.dropUser('mysun')           

八:mongoDB的副本集配置(重要)

副本集

​ 官方認為至少要三台節點才可以做副本集,主節點提供讀寫,從庫隻負責讀 ,但是和MYSQL主從不一樣,MongoDB的副本集每個節點都知道對方的資訊情況,假如主節點當機,那麼在副本集叢集中就會依據大多數投票選舉來進行,然後再比較資料的新舊來确定新的主節點,比如三個節點挂掉一台剩下兩台依舊滿足大多數,從庫自動指向新的主庫,而原來當機的主節點變為從節點,重新指向新的主節點,叢集還是正常的。

仲裁節點

MongoDB中除了master,slave節點,還有一個仲裁節點Arbiter,比如現在隻有兩台伺服器,按之前的做法副本集是不可行的,最少三台,但是Arbiter節點的出現兩台伺服器也可以實作,Arbiter節點隻負責投票,不存儲也不處理資料,幾乎不消耗資源,并且永遠不會搶占master,在兩台中的任何一台上起一個Arbiter執行個體,實體上是兩台,但是邏輯上有三台,副本集也可以搭建。           

實驗環境采用一台多執行個體進行的

1.建立節點目錄和資料目錄

systemctl stop mongod #關閉原來的測試MongoDB
mkdir -p /opt/mongo_2801{7,8,9}/{conf,log,pid}  
mkdir -p /data/mongo_2801{7,8,9}           

2.建立配置檔案

vim /opt/mongo_28017/conf/mongo_28017.conf

systemLog:
  destination: file   
  logAppend: true  
  path: /opt/mongo_28017/log/mongodb.log

storage:
  journal:
    enabled: true
  dbPath: /data/mongo_28017
  directoryPerDB: true
  wiredTiger:
     engineConfig:
        cacheSizeGB: 0.5 
        directoryForIndexes: true
     collectionConfig:
        blockCompressor: zlib
     indexConfig:
        prefixCompression: true

processManagement:
  fork: true
  pidFilePath: /opt/mongo_28017/pid/mongod.pid

net:
  port: 28017
  bindIp: 127.0.0.1,10.0.0.51

replication:   #該節點是以副本級啟動的
   oplogSizeMB: 1024  #相當于MYSQL的binlog,指定記錄日志的大小為1G
   replSetName: dba    #在一個組中啟動,名叫dba           

3.複制配置檔案到其他節點

cp /opt/mongo_28017/conf/mongo_28017.conf /opt/mongo_28018/conf/mongo_28018.conf
cp /opt/mongo_28017/conf/mongo_28017.conf /opt/mongo_28019/conf/mongo_28019.conf           

4.替換端口号

sed -i 's#28017#28018#g' /opt/mongo_28018/conf/mongo_28018.conf  
sed -i 's#28017#28019#g' /opt/mongo_28019/conf/mongo_28019.conf           

5.啟動所有節點

mongod -f /opt/mongo_28017/conf/mongo_28017.conf
mongod -f /opt/mongo_28018/conf/mongo_28018.conf
mongod -f /opt/mongo_28019/conf/mongo_28019.conf           

6.初始化叢集,一定要在主節點上初始化

mongo 10.0.0.51:28019   #指定端口來進入MongoDB執行個體           
config = {
            _id : "dba",
            members : [
                        {_id : 0, host : "192.168.15.253:27017"},
                        {_id : 1, host : "192.168.15.248:27017"},
                        {_id : 2, host : "192.168.15.247:27017"},
            ]}
rs.initiate(config)           

7.插入資料測試,看看從節點能不能同步

db.inventory.insertMany( [
    { "item": "journal", "qty": 25, "size": { "h": 14, "w": 21, "uom": "cm" }, "status": "A" },
    { "item": "notebook", "qty": 50, "size": { "h": 8.5, "w": 11, "uom": "in" }, "status": "A" },
    { "item": "paper", "qty": 100, "size": { "h": 8.5, "w": 11, "uom": "in" }, "status": "D" },
    { "item": "planner", "qty": 75, "size": { "h": 22.85, "w": 30, "uom": "cm" }, "status": "D" },
    { "item": "postcard", "qty": 45, "size": { "h": 10, "w": 15.25, "uom": "cm" }, "status": "A" }
]);           

8.副本節點登入檢視資料,預設剛開始進去不能讀取,需要指定rs.slaveok()參數

rs.slaveOk()
use test
db.inventory.find()           

9.設定副本可讀

方法1:臨時生效
rs.slaveOk()
方法2:寫入啟動檔案,永久生效
echo "rs.slaveOk()" > /root/.mongorc.js           

九:mongoDB的副本集權重調整

0.模拟故障轉移

mongod -f /opt/mongo_28017/conf/mongo_28017.conf --shutdown
mongod -f /opt/mongo_28017/conf/mongo_28017.conf           

1.檢視目前副本集配置

rs.conf()

2.設定權重(權重越大,優先級越高)

rs.conf()  #檢視目前副本集的優先級
config=rs.conf() #将目前配置資訊導入到變量中儲存
config.members[0].priority=100  #0代表節點的編号,将編号為0的節點權重改為100
rs.reconfig(config)  #重新載入配置資訊           

3.恢複成預設的權重,以便後面不影響主節點的選舉

config=rs.conf()
config.members[0].priority=1 #毀屍滅迹
rs.reconfig(config)
rs.conf() #檢視           

4.主節點主動降級,用于比如需要停機維護,未當機,隻是放棄競選主節點,其他節點繼續競選

rs.stepDown() #執行完就變成從節點,主動放棄           
rs.status()檢視副本集詳細資訊           

5:但是有一個問題,那麼正常業務的代碼怎麼才可以連接配接到這個叢集呢?

先來說一下,所有rs開頭的指令都是和副本級相關的

rs.isMaster()    #檢視誰是主節點           
[10.0.0.51:28017,10.0.0.52:28018,10.0.0.53:28019] #MongoDB的叢集會将位址全部寫在一個集合中,由程式去統一調用,程式會先rs.isMaster()執行檢視誰是master,知道後程式再去連接配接這個master,如果這個master當機,隻要叢集還能正常工作,那麼就會繼續選取重新連接配接!           

十:mongoDB增加新節點和删除舊節點(擴容和縮減)

但凡是叢集,都有擴容和收縮叢集的需要,注意,在沒有仲裁節點之前,3台機器構成的叢集隻能壞一台,4台機器在沒有仲裁節點之前,也是隻能壞一台,如果壞掉兩台就不滿足成員大多數,即不能壞掉隻剩兩台

1.建立新節點并啟動

mkdir -p /opt/mongo_28010/{conf,log,pid}
mkdir -p /data/mongo_28010
cp /opt/mongo_28017/conf/mongo_28017.conf /opt/mongo_28010/conf/mongo_28010.conf
sed -i 's#28017#28010#g' /opt/mongo_28010/conf/mongo_28010.conf
mongod -f /opt/mongo_28010/conf/mongo_28010.conf
mongo db01:28010  #登入新的節點           

2.叢集添加節點,一定是在主節點上添加,并且新添加的節點不需要初始化,直接添加使用

mongo 10.0.0.51:28017  #登入主節點
use admin
rs.add("10.0.0.51:28010")  #在主節點上執行該指令,将新的節點加入到叢集中。           

3.新節點檢視資訊

mongo db01:28010 #這裡的db01已經在/etc/hosts裡面做了解析了           

3.删除節點

rs.remove("db01:28010")
rs.remove("db01:28011")           

十一:mongoDB的仲裁節點

為了解決在最少的機器使用前提下,盡量減少當機數量帶來的危險情況。

1.不存儲資料也不處理資料

2.隻負責投票

3.永遠不會搶占master角色

4.不消耗太多資源

仲裁節點的加入,使得從之前的四個節點叢集最多壞一台減小到壞兩台

mkdir -p /opt/mongo_28011/{conf,log,pid}
mkdir -p /data/mongo_28011
cp /opt/mongo_28017/conf/mongo_28017.conf /opt/mongo_28011/conf/mongo_28011.conf
sed -i 's#28017#28011#g' /opt/mongo_28011/conf/mongo_28011.conf
mongod -f /opt/mongo_28011/conf/mongo_28011.conf
mongo db01:28011           

2.将仲裁節點加入叢集

rs.addArb("192.168.15.247:27017")