MongoDB要點

MongoDB

1、介紹

MongoDB是用C++語言編寫的非關係型數據庫。特色是高性能、易部署、易使用,存儲數據十分方便,主要特性有:mysql

  • 面向集合存儲,易於存儲對象類型的數據
  • 模式自由
  • 支持動態查詢
  • 支持徹底索引,包含內部對象
  • 支持複製和故障恢復
  • 使用高效的二進制數據存儲,包括大型對象
  • 文件存儲格式爲BSON(一種JSON的擴展)

MongoDB基本概念

  • 文檔(document)是MongoDB中數據的基本單元,很是相似於關係型數據庫系統中的行(可是比行要複雜的多)。
  • 集合(collection)就是一組文檔,若是說MongoDB中的文檔相似於關係型數據庫中的行,那麼集合就如同表。
  • MongoDB的單個計算機能夠容納多個獨立的數據庫,每個數據庫都有本身的集合和權限。
  • MongoDB自帶簡潔但功能強大的JavaScript shell,這個工具對於管理MongoDB實例和操做數據做用很是大。
  • 每個文檔都有一個特殊的鍵」_id」,它在文檔所處的集合中是惟一的,至關於關係數據庫中的表的主鍵。

2、安裝

一、系統準備

(1)redhat或cnetos6.2以上系統
(2)系統開發包完整
(3)ip地址和hosts文件解析正常
(4)iptables防火牆&SElinux關閉
(5)關閉大頁內存機制
    
# 2.關閉大頁內存機制
root用戶下
# 追加到配置文件,每次開機自啓動
cat >>/etc/rc.local <<EOF
if test -f /sys/kernel/mm/transparent_hugepage/enabled; then
  echo never > /sys/kernel/mm/transparent_hugepage/enabled
fi
if test -f /sys/kernel/mm/transparent_hugepage/defrag; then
   echo never > /sys/kernel/mm/transparent_hugepage/defrag
fi
EOF 

# 或者在命令行直接運行,可是開機不會自啓動
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag


# 爲何要關閉
透明大頁面(THP)是一個Linux內存管理系統
這樣就減小了轉換後備緩衝區(TLB)的開銷。
經過使用更大的內存頁查找具備大量內存的計算機。
可是,數據庫工做負載在THP中一般表現不佳,
由於它們每每具備稀疏而不是連續的內存訪問模式。
您應該在Linux機器上禁用THP,以確保MongoDB的最佳性能。

2.mongodb安裝

# 1.建立所需用戶和組 最好不用root用戶操做
groupadd -g 800 mongod
useradd -u 801 -g mongod mongod
passwd mongod
# 2.建立mongodb所需目錄結構
mkdir -p /mongodb/bin
mkdir -p /mongodb/conf
mkdir -p /mongodb/log
mkdir -p /mongodb/data


# 3.上傳並解壓軟件到指定位置
# 上傳到:
cd   /opt/
# 解壓:
tar xf mongodb-linux-x86_64-rhel70-3.4.16.tgz

# 拷貝目錄下bin程序到/mongodb/bin
cp -a /opt/mongodb-linux-x86_64-rhel70-3.4.16/bin/* /mongodb/bin

# 4.設置目錄結構權限

chown -R mongod:mongod /mongodb

# 5.設置用戶環境變量
# 切換到mongod用戶
su - mongod

cat >> .bash_profile << EOF
export PATH=/mongodb/bin:$PATH
EOF

source .bash_profile


# 6.啓動mongodb
mongod --dbpath=/mongodb/data --logpath=/mongodb/log/mongodb.log --port=27017 --logappend --fork 

# 7.登陸mongodb
[mongod@server2 ~]$ mongo


# 8.使用配置文件登陸

vim /mongodb/conf/mongodb.conf

logpath=/mongodb/log/mongodb.log
dbpath=/mongodb/data 
port=27017 
fork=true

# 9.關閉mongodb
mongod -f /mongodb/conf/mongodb.conf --shutdown
# 10.使用配置文件啓動mongodb
mongod -f /mongodb/conf/mongodb.conf

3.mongodb配置YAML模式

# 在之後,向這樣的xxx=xxx的形式可能要淘汰了
logpath=/mongodb/log/mongodb.log
dbpath=/mongodb/data 
port=27017 
fork=true

# 推薦使用YAML模式
# YAML模式裏不容許使用tab健

# 系統日誌有關  
systemLog:
   destination: file        
   path: "/mongodb/log/mongodb.log"    # 日誌位置
   logAppend: true                     # 日誌以追加模式記錄

# 數據存儲有關   
storage:
   journal:
      enabled: true
   dbPath: "/mongodb/data"            # 數據路徑的位置
   
# 進程控制  
processManagement:
   fork: true                         # 後臺守護進程
   pidFilePath: <string>              # pid文件的位置,通常不用配置,能夠去掉這行,自動生成到data中
   
   
# 網絡配置有關   
net:            
   bindIp: <ip>                       # 監聽地址,若是不配置這行是監聽在0.0.0.0
   port: <port>                       # 端口號,默認不配置端口號,是27017
   
# 安全驗證有關配置      
security:
  authorization: enabled              # 是否打開用戶名密碼驗證
  
  
  
------------------如下是複製集與分片集羣有關---------------------

replication:
 oplogSizeMB: <NUM>
 replSetName: "<REPSETNAME>"
 secondaryIndexPrefetch: "all"
sharding:
   clusterRole: <string>
   archiveMovedChunks: <boolean>
   
   
---for mongos only
replication:
   localPingThresholdMs: <int>

sharding:
   configDB: <string>
    
    
    
# 實例
# mongodb基礎配置YAML模式
cat >> /mongodb/conf/mongo.conf << EOF
systemLog:
   destination: file
   path: "/mongodb/log/mongodb.log"
   logAppend: true
storage:
   journal:
      enabled: true
   dbPath: "/mongodb/data/"
processManagement:
   fork: true
net:
   port: 27017
EOF
   
# 關閉並以配置啓動
mongod -f /mongodb/conf/mongo.conf --shutdown
mongod -f /mongodb/conf/mongo.conf

3、mongodb經常使用基本操做

1.mongodb 默認存在的庫

test:登陸時默認存在的庫
admin庫:系統預留庫,mongodb系統管理庫
local庫:本地預留庫,存儲關鍵日誌

2.mongodb對象操做

mongo         mysql
庫    ----->  庫
集合  ----->  表
文檔  ----->  數據行

3.命令分類

# 庫(database)
# 建立數據庫:
當use的時候,系統就會自動建立一個數據庫。
若是use以後沒有建立任何集合。
系統就會刪除這個數據庫。
# 刪除數據庫
若是沒有選擇任何數據庫,會刪除默認的test數據庫
# 顯示全部庫
show  databases 
show  dbs
# 切換庫
use   oldguo

-------------------------------
# 表(collection集合)
# 查看當前數據下的全部集合
show tables
show collections
db.getCollectionNames()
# 建立集合
# 方法一
db.createCollection('a')
# 方法2:當插入一個文檔的時候,一個集合就會自動建立。
use oldguo
# 在oldguo庫下建立表(集合)並插入{id:101,name:"zhangsan",age:20,gender:"m"}
db.stu.insert({id:101,name:"zhangsan",age:20,gender:"m"})

# 刪除集合
use oldguo
db.log.drop() 

# 重命名集合
# 把log更名爲log1
db.log.renameCollection("log1")
----------------------------------------------

# 數據行(document)
# 查詢數據:
# 整行顯示
db.stu.find({})
# 格式顯示
db.stu.find({}).pretty()
# 指定查找
db.stu.find({id:101}).pretty();
# 注:默認每頁顯示20條記錄,當顯示不下的的狀況下,能夠用it迭代命令查詢下一頁數據。
# 設置每頁顯示數據的大小:
DBQuery.shellBatchSize=50; //每頁顯示50條記錄
# 查看第1條記錄
db.log.findOne() 
# 查詢總的記錄數
db.log.count() 

# 刪除集合中的記錄數
app> db.log.remove({}) //刪除集合中全部記錄
> db.log.distinct("name") //查詢去掉當前集合中某列的重複數據


# 查看集合存儲信息
app> db.log.stats()
app> db.log.dataSize() //集合中數據的原始大小
app> db.log.totalIndexSize() //集合中索引數據的原始大小
app> db.log.totalSize() //集合中索引+數據壓縮存儲以後的大小
app> db.log.storageSize() //集合中數據壓縮存儲的大小

-------------------------------------------
# db.命令:
# 相似於linux中的tab功能
db.[TAB]  
# db級別的命令使用幫助
db.help() 
# 查看當前db版本
db.version()
# 顯示當前數據庫
db
# 或
db.getName()
# 顯示當前數據庫狀態
db.stats()
# 查看當前數據庫的鏈接機器地址
db.getMongo()

4、用戶管理

1.語法格式

# 注意:
# 驗證庫,創建用戶時use到的庫,在使用用戶時,要加上驗證庫才能登錄。
# 對於管理員用戶,必須在admin下建立.


# 基本語法
db.createUser(
{
    user: "<name>",
    pwd: "<cleartext password>",
    roles: [
       { 
           role: "<role>",
           db: "<database>" 
       },
    ...
    ]
})
# 基本語法說明:

user:用戶名
pwd:密碼
roles:
    role:角色名
    db:做用對象
    
role:root, readWrite,read  

# 驗證數據庫:

# mongo -u oldguo -p 123 10.0.0.200/驗證庫名
# 總結:
  一、在建立普通用戶時,通常事先use 到想要設置權限的庫下;或者全部普通用戶使用同一個驗證庫,好比test
  二、root角色的建立,要在admin下進行建立
  三、建立用戶時你use到的庫,在未來登陸時候,使用如下方式登陸,不然是登陸不了的


# 查詢mongodb中的用戶信息
mongo -uroot -proot123 10.0.0.200/admin
db.system.users.find().pretty()


 
# 刪除用戶(root身份登陸,use到驗證庫)
# 刪除用戶
mongo -uroot -proot123 10.0.0.200/admin
use app
db.dropUser("app01")

2.實例

# 1.建立超級管理員:管理全部數據庫(必須use admin再去建立)
use admin
db.createUser(
{
    user: "root",
    pwd: "root123",
    roles: [ { role: "root", db: "admin" } ]
}
)


# 2.驗證用戶
db.auth('root','root123')


# 3.配置文件中,追加如下配置,開啓驗證功能
cat >> /mongodb/conf/mongo.conf << EOF
security:
  authorization: enabled
EOF


# 4.重啓mongodb
mongod -f /mongodb/conf/mongo.conf --shutdown 
mongod -f /mongodb/conf/mongo.conf 

# 5.登陸驗證,進入的默認是驗證庫
mongo -uroot -proot123  admin
mongo -uroot -proot123  10.0.0.200/admin

# 或者
mongo
use admin
db.auth('root','root123')

# 查看用戶:
use admin
db.system.users.find().pretty()
---------------------------------------------------------


# 1.建立app數據庫讀寫權限的用戶並對test數據庫具備讀權限:
mongo -uroot -proot123 10.0.0.200/admin

use app

db.createUser(
{
user: "app03",
pwd: "app03",
roles: [ { role: "readWrite", db: "app" },
{ role: "read", db: "test" }
]
}
)
# 測試
mongo -uapp03 -papp03 10.0.0.200/app

5、mongodb複製集(Replcation Set)

1.基本原理

​ 基本構成是1主2從的結構,自帶互相監控投票機制(Raft(MongoDB) Paxos(mysql MGR 用的是變種))
​ 若是發生主庫宕機,複製集內部會進行投票選舉,選擇一個新的主庫替代原有主庫對外提供服務。同時複製集會自動通知客戶端程序,主庫已經發生切換了。應用就會鏈接到新的主庫。linux

2.複製的基本架構

一個包含3個mongod的複製集架構以下所示算法

img

若是主服務器失效,會變成:sql

img

若是加上可選的仲裁者:mongodb

img

若是主服務器失效:shell

img

3.配置

# 三個以上的mongodb節點(或多實例)
# 多個端口:2801七、2801八、2801九、28020
# 1.建立節點多套目錄:
mkdir -p /mongodb/28017/conf /mongodb/28017/data /mongodb/28017/log
mkdir -p /mongodb/28018/conf /mongodb/28018/data /mongodb/28018/log
mkdir -p /mongodb/28019/conf /mongodb/28019/data /mongodb/28019/log
mkdir -p /mongodb/28020/conf /mongodb/28020/data /mongodb/28020/log


# 2.配置多套配置文件
# 配置文件內容:
cat >>/mongodb/28017/conf/mongod.conf << EOF
systemLog:
  destination: file
  path: /mongodb/28017/log/mongodb.log
  logAppend: true
storage:
  journal:
    enabled: true
  dbPath: /mongodb/28017/data
  directoryPerDB: true
  #engine: wiredTiger
  wiredTiger:
    engineConfig:
      cacheSizeGB: 1
      directoryForIndexes: true
    collectionConfig:
      blockCompressor: zlib
    indexConfig:
      prefixCompression: true
processManagement:
  fork: true
net:
  port: 28017
replication:
  oplogSizeMB: 2048
  replSetName: my_repl
EOF     

cp  /mongodb/28017/conf/mongod.conf  /mongodb/28018/conf/
cp  /mongodb/28017/conf/mongod.conf  /mongodb/28019/conf/
cp  /mongodb/28017/conf/mongod.conf  /mongodb/28020/conf/

sed 's#28017#28018#g' /mongodb/28018/conf/mongod.conf -i
sed 's#28017#28019#g' /mongodb/28019/conf/mongod.conf -i
sed 's#28017#28020#g' /mongodb/28020/conf/mongod.conf -i



# 3.啓動多個實例備用
mongod -f /mongodb/28017/conf/mongod.conf
mongod -f /mongodb/28018/conf/mongod.conf
mongod -f /mongodb/28019/conf/mongod.conf
mongod -f /mongodb/28020/conf/mongod.conf

# 4.端口檢測
netstat -lnp|grep 280


# 5.配置複製集
# 1主2從,從庫普通從庫
# 鏈接隨便一個節點
mongo --port 28017 admin
# 配置主從信息
config = {_id: 'my_repl', members: [
                          {_id: 0, host: '10.0.0.200:28017'},
                          {_id: 1, host: '10.0.0.200:28018'},
                          {_id: 2, host: '10.0.0.200:28019'}]
          }     
# 使用配置
rs.initiate(config) 

# 查詢複製集狀態
rs.status();
# 主節點可讀可寫,從節點只讀

# 1主1從1個arbiter

mongo -port 28017 admin

config = {_id: 'my_repl', members: [
                          {_id: 0, host: '10.0.0.200:28017'},
                          {_id: 1, host: '10.0.0.200:28018'},
                          {_id: 2, host: '10.0.0.200:28019',"arbiterOnly":true}]
          }
                   
rs.initiate(config)

4.複製集管理操做

# 1.查看複製集狀態:
rs.status();    //查看總體複製集狀態
rs.isMaster(); // 查看當前是不是主節點

# 2.添加刪除節點
rs.remove("ip:port"); // 刪除一個節點
rs.add("ip:port"); // 新增從節點
rs.addArb("ip:port"); // 新增仲裁節點

# 注:
添加特殊節點時,
    1.能夠在搭建過程當中設置特殊節點
    2.能夠經過修改配置的方式將普通從節點設置爲特殊節點

5.特殊節點

# 特殊節點:
    arbiter節點:主要負責選主過程當中的投票,可是不存儲任何數據,也不提供任何服務
    hidden節點:隱藏節點,不參與選主,也不對外提供服務。
    delay節點:延時節點,數據落後於主庫一段時間,由於數據是延時的,也不該該提供服務或參與選主,因此一般會配合hidden(隱藏)

# 注:通常狀況下會將delay+hidden一塊兒配置使用

# 1.添加 arbiter節點
# 鏈接到主節點
[mongod@db03 ~]$ mongo --port 28018 admin
# 添加仲裁節點
my_repl:PRIMARY> rs.addArb("10.0.0.200:28020")
# 查看節點狀態
my_repl:PRIMARY> rs.isMaster()
{
    "hosts" : [
        "10.0.0.200:28017",
        "10.0.0.200:28018",
        "10.0.0.200:28019"
    ],
    "arbiters" : [
        "10.0.0.200:28020"
    ],
}

6.其餘操做命令

# 查看副本集的配置信息
admin> rs.config()
# 或者
admin> rs.conf()

# 查看副本集各成員的狀態
admin> rs.status()

# 副本集角色切換(不要人爲隨便操做)
admin> rs.stepDown()
# 注:
admin> rs.freeze(300) # 鎖定從,使其不會轉變成主庫
# freeze()和stepDown單位都是秒。

# 設置副本節點可讀:在副本節點執行
admin> rs.slaveOk()

eg:
admin> use app
switched to db app
app> db.createCollection('a')
{ "ok" : 0, "errmsg" : "not master", "code" : 10107 }

# 查看副本節點(監控主從延時)
admin> rs.printSlaveReplicationInfo()
source: 192.168.1.22:27017
    syncedTo: Thu May 26 2016 10:28:56 GMT+0800 (CST)
    0 secs (0 hrs) behind the primary

6、MongoDB Sharding Cluster 分片集羣

  分片(sharding)是MongoDB用來將大型集合分割到不一樣服務器(或者說一個集羣)上所採用的方法。儘管分片起源於關係型數據庫分區,但MongoDB分片徹底又是另外一回事。數據庫

  和MySQL分區方案相比,MongoDB的最大區別在於它幾乎能自動完成全部事情,只要告訴MongoDB要分配數據,它就能自動維護數據在不一樣服務器之間的均衡。json

1.MongoDB分片介紹

1.1 分片的目的

  高數據量和吞吐量的數據庫應用會對單機的性能形成較大壓力,大的查詢量會將單機的CPU耗盡,大的數據量對單機的存儲壓力較大,最終會耗盡系統的內存而將壓力轉移到磁盤IO上。vim

  爲了解決這些問題,有兩個基本的方法: 垂直擴展和水平擴展。

    垂直擴展:增長更多的CPU和存儲資源來擴展容量。

    水平擴展:將數據集分佈在多個服務器上。水平擴展即分片。

1.2 分片設計思想

  分片爲應對高吞吐量與大數據量提供了方法。使用分片減小了每一個分片須要處理的請求數,所以,經過水平擴展,集羣能夠提升本身的存儲容量和吞吐量。舉例來講,當插入一條數據時,應用只須要訪問存儲這條數據的分片.

  使用分片減小了每一個分片存儲的數據。

  例如,若是數據庫1tb的數據集,並有4個分片,而後每一個分片可能僅持有256 GB的數據。若是有40個分片,那麼每一個切分可能只有25GB的數據。

img

1.3 分片機制提供了以下三種優點

  1. 對集羣進行抽象,讓集羣「不可見」

    ​ MongoDB自帶了一個叫作mongos的專有路由進程。mongos就是掌握統一路口的路由器,其會將客戶端發來的請求準確無誤的路由到集羣中的一個或者一組服務器上,同時會把接收到的響應拼裝起來發回到客戶端。

  2. 保證集羣老是可讀寫

    ​ MongoDB經過多種途徑來確保集羣的可用性和可靠性。將MongoDB的分片和複製功能結合使用,在確保數據分片到多臺服務器的同時,也確保了每分數據都有相應的備份,這樣就能夠確保有服務器換掉時,其餘的從庫能夠當即接替壞掉的部分繼續工做。

  3. 使集羣易於擴展

    ​ 當系統須要更多的空間和資源的時候,MongoDB使咱們能夠按需方便的擴充系統容量。

1.4 分片集羣架構

組件 說明
Config Server 存儲集羣全部節點、分片數據路由信息。默認須要配置3個Config Server節點。
Mongos 提供對外應用訪問,全部操做均經過mongos執行。通常有多個mongos節點。數據遷移和數據自動平衡。mongos自己沒有任何數據,他也不知道該怎麼處理這數據,去找config server
Mongod 存儲應用數據記錄。通常有多個Mongod節點,達到數據分片目的。真正的數據存儲位置,以chunk爲單位存數據。

​ Mongos自己並不持久化數據,Sharded cluster全部的元數據都會存儲到Config Server,而用戶的數據會議分散存儲到各個shard。Mongos啓動後,會從配置服務器加載元數據,開始提供服務,將用戶的請求正確路由到對應的碎片。

2 集羣中數據分佈

2.1 Chunk是什麼

  在一個shard server內部,MongoDB仍是會把數據分爲chunks,每一個chunk表明這個shard server內部一部分數據。chunk的產生,會有如下兩個用途:

  Splitting:當一個chunk的大小超過配置中的chunk size時,MongoDB的後臺進程會把這個chunk切分紅更小的chunk,從而避免chunk過大的狀況

  Balancing:在MongoDB中,balancer是一個後臺進程,負責chunk的遷移,從而均衡各個shard server的負載,系統初始1個chunk,chunk size默認值64M,生產庫上選擇適合業務的chunk size是最好的。ongoDB會自動拆分和遷移chunks。

分片集羣的數據分佈(shard節點)

(1)使用chunk來存儲數據

(2)進羣搭建完成以後,默認開啓一個chunk,大小是64M,

(3)存儲需求超過64M,chunk會進行分裂,若是單位時間存儲需求很大,設置更大的chunk

(4)chunk會被自動均衡遷移。

2.2 chunksize的選擇

  適合業務的chunksize是最好的。

  chunk的分裂和遷移很是消耗IO資源;chunk分裂的時機:在插入和更新,讀數據不會分裂。

  chunksize的選擇:

  小的chunksize:數據均衡是遷移速度快,數據分佈更均勻。數據分裂頻繁,路由節點消耗更多資源。大的chunksize:數據分裂少。數據塊移動集中消耗IO資源。一般100-200M

2.3 chunk分裂及遷移

  隨着數據的增加,其中的數據大小超過了配置的chunk size,默認是64M,則這個chunk就會分裂成兩個。數據的增加會讓chunk分裂得愈來愈多。

img

  這時候,各個shard 上的chunk數量就會不平衡。這時候,mongos中的一個組件balancer 就會執行自動平衡。把chunk從chunk數量最多的shard節點挪動到數量最少的節點。

img

chunkSize 對分裂及遷移的影響

  MongoDB 默認的 chunkSize 爲64MB,如無特殊需求,建議保持默認值;chunkSize 會直接影響到 chunk 分裂、遷移的行爲。

  chunkSize 越小,chunk 分裂及遷移越多,數據分佈越均衡;反之,chunkSize 越大,chunk 分裂及遷移會更少,但可能致使數據分佈不均。

  chunkSize 過小,容易出現 jumbo chunk(即shardKey 的某個取值出現頻率很高,這些文檔只能放到一個 chunk 裏,沒法再分裂)而沒法遷移;chunkSize 越大,則可能出現 chunk 內文檔數太多(chunk 內文檔數不能超過 250000 )而沒法遷移。

  chunk 自動分裂只會在數據寫入時觸發,因此若是將 chunkSize 改小,系統須要必定的時間來將 chunk 分裂到指定的大小。

  chunk 只會分裂,不會合並,因此即便將 chunkSize 改大,現有的 chunk 數量不會減小,但 chunk 大小會隨着寫入不斷增加,直到達到目標大小。

3 數據區分

3.1 分片鍵shard key

  MongoDB中數據的分片是、以集合爲基本單位的,集合中的數據經過片鍵(Shard key)被分紅多部分。其實片鍵就是在集合中選一個鍵,用該鍵的值做爲數據拆分的依據。

  因此一個好的片鍵對分片相當重要。片鍵必須是一個索引,經過sh.shardCollection加會自動建立索引(前提是此集合不存在的狀況下)。一個自增的片鍵對寫入和數據均勻分佈就不是很好,由於自增的片鍵總會在一個分片上寫入,後續達到某個閥值可能會寫到別的分片。可是按照片鍵查詢會很是高效。

  隨機片鍵對數據的均勻分佈效果很好。注意儘可能避免在多個分片上進行查詢。在全部分片上查詢,mongos會對結果進行歸併排序。

  對集合進行分片時,你須要選擇一個片鍵,片鍵是每條記錄都必須包含的,且創建了索引的單個字段或複合字段,MongoDB按照片鍵將數據劃分到不一樣的數據塊中,並將數據塊均衡地分佈到全部分片中。

  爲了按照片鍵劃分數據塊,MongoDB使用基於範圍的分片方式或者 基於哈希的分片方式。

注意:

分片鍵是不可變。

分片鍵必須有索引。

分片鍵大小限制512bytes。

分片鍵用於路由查詢。

MongoDB不接受已進行collection級分片的collection上插入無分片

鍵的文檔(也不支持空值插入)

3.2 以範圍爲基礎的分片Sharded Cluster

  Sharded Cluster支持將單個集合的數據分散存儲在多shard上,用戶能夠指定根據集合內文檔的某個字段即shard key來進行範圍分片(range sharding)。

img

  對於基於範圍的分片,MongoDB按照片鍵的範圍把數據分紅不一樣部分。

  假設有一個數字的片鍵:想象一個從負無窮到正無窮的直線,每個片鍵的值都在直線上畫了一個點。MongoDB把這條直線劃分爲更短的不重疊的片斷,並稱之爲數據塊,每一個數據塊包含了片鍵在必定範圍內的數據。在使用片鍵作範圍劃分的系統中,擁有」相近」片鍵的文檔極可能存儲在同一個數據塊中,所以也會存儲在同一個分片中。

3.3 基於哈希的分片

  分片過程當中利用哈希索引做爲分片的單個鍵,且哈希分片的片鍵只能使用一個字段,而基於哈希片鍵最大的好處就是保證數據在各個節點分佈基本均勻。

img

  對於基於哈希的分片,MongoDB計算一個字段的哈希值,並用這個哈希值來建立數據塊。在使用基於哈希分片的系統中,擁有」相近」片鍵的文檔極可能不會存儲在同一個數據塊中,所以數據的分離性更好一些。

  Hash分片與範圍分片互補,能將文檔隨機的分散到各個chunk,充分的擴展寫能力,彌補了範圍分片的不足,但不能高效的服務範圍查詢,全部的範圍查詢要分發到後端全部的Shard才能找出知足條件的文檔。

3.4 分片鍵選擇建議

一、遞增的sharding key

數據文件挪動小。(優點)

由於數據文件遞增,因此會把insert的寫IO永久放在最後一片上,形成最後一片的寫熱點。同時,隨着最後一片的數據量增大,將不斷的發生遷移至以前的片上。

二、隨機的sharding key

數據分佈均勻,insert的寫IO均勻分佈在多個片上。(優點)

大量的隨機IO,磁盤不堪重荷。

三、混合型key

大方向隨機遞增,小範圍隨機分佈。

爲了防止出現大量的chunk均衡遷移,可能形成的IO壓力。咱們須要設置合理分片使用策略(片鍵的選擇、分片算法(range、hash))

分片注意:

分片鍵是不可變、分片鍵必須有索引、分片鍵大小限制512bytes、分片鍵用於路由查詢。

MongoDB不接受已進行collection級分片的collection上插入無分片鍵的文檔(也不支持空值插入)

4.部署分片集羣

# 10個實例:38017-38026

# configserver:
3臺構成的複製集(1主兩從,不支持arbiter)38018-38020(複製集名字configsvr)

# shard節點:

sh1:38021-23    (1主兩從,其中一個節點爲arbiter,複製集名字sh1)
sh2:38024-26    (1主兩從,其中一個節點爲arbiter,複製集名字sh2)
# shard複製集配置:
# 1.目錄建立:
mkdir -p /mongodb/38021/conf  /mongodb/38021/log  /mongodb/38021/data
mkdir -p /mongodb/38022/conf  /mongodb/38022/log  /mongodb/38022/data
mkdir -p /mongodb/38023/conf  /mongodb/38023/log  /mongodb/38023/data
mkdir -p /mongodb/38024/conf  /mongodb/38024/log  /mongodb/38024/data
mkdir -p /mongodb/38025/conf  /mongodb/38025/log  /mongodb/38025/data
mkdir -p /mongodb/38026/conf  /mongodb/38026/log  /mongodb/38026/data

# 2.修改配置文件:

# sh1:
cat >> /mongodb/38021/conf/mongodb.conf <<EOF
systemLog:
  destination: file
  path: /mongodb/38021/log/mongodb.log   
  logAppend: true
storage:
  journal:
    enabled: true
  dbPath: /mongodb/38021/data
  directoryPerDB: true
  #engine: wiredTiger
  wiredTiger:
    engineConfig:
      cacheSizeGB: 1
      directoryForIndexes: true
    collectionConfig:
      blockCompressor: zlib
    indexConfig:
      prefixCompression: true
net:
  port: 38021
replication:
  oplogSizeMB: 2048
  replSetName: sh1
sharding:
  clusterRole: shardsvr
processManagement: 
  fork: true
EOF

cp  /mongodb/38021/conf/mongodb.conf  /mongodb/38022/conf/
cp  /mongodb/38021/conf/mongodb.conf  /mongodb/38023/conf/
sed 's#38021#38022#g' /mongodb/38022/conf/mongodb.conf -i
sed 's#38021#38023#g' /mongodb/38023/conf/mongodb.conf -i


# sh2:
cat >> /mongodb/38024/conf/mongodb.conf << EOF
systemLog:
  destination: file
  path: /mongodb/38024/log/mongodb.log   
  logAppend: true
storage:
  journal:
    enabled: true
  dbPath: /mongodb/38024/data
  directoryPerDB: true
  wiredTiger:
    engineConfig:
      cacheSizeGB: 1
      directoryForIndexes: true
    collectionConfig:
      blockCompressor: zlib
    indexConfig:
      prefixCompression: true
net:
  port: 38024
replication:
  oplogSizeMB: 2048
  replSetName: sh2
sharding:
  clusterRole: shardsvr
processManagement: 
  fork: true
EOF

cp  /mongodb/38024/conf/mongodb.conf  /mongodb/38025/conf/
cp  /mongodb/38024/conf/mongodb.conf  /mongodb/38026/conf/
sed 's#38024#38025#g' /mongodb/38025/conf/mongodb.conf -i
sed 's#38024#38026#g' /mongodb/38026/conf/mongodb.conf -i

# 3啓動全部節點,並搭建複製集:

mongod -f  /mongodb/38021/conf/mongodb.conf 
mongod -f  /mongodb/38022/conf/mongodb.conf 
mongod -f  /mongodb/38023/conf/mongodb.conf 
mongod -f  /mongodb/38024/conf/mongodb.conf 
mongod -f  /mongodb/38025/conf/mongodb.conf 
mongod -f  /mongodb/38026/conf/mongodb.conf  


# 搭建sh1複製集
mongo --port 38021
use  admin
config = {_id: 'sh1', members: [
                          {_id: 0, host: '10.0.0.200:38021'},
                          {_id: 1, host: '10.0.0.200:38022'},
                          {_id: 2, host: '10.0.0.200:38023',"arbiterOnly":true}]
           }

rs.initiate(config)
  
# 搭建sh2複製集 
mongo --port 38024 
use admin
config = {_id: 'sh2', members: [
                          {_id: 0, host: '10.0.0.200:38024'},
                          {_id: 1, host: '10.0.0.200:38025'},
                          {_id: 2, host: '10.0.0.200:38026',"arbiterOnly":true}]
           }
  
rs.initiate(config)
# config節點配置:

# 1目錄建立:
mkdir -p /mongodb/38018/conf  /mongodb/38018/log  /mongodb/38018/data
mkdir -p /mongodb/38019/conf  /mongodb/38019/log  /mongodb/38019/data
mkdir -p /mongodb/38020/conf  /mongodb/38020/log  /mongodb/38020/data

# 2修改配置文件:

cat >> /mongodb/38018/conf/mongodb.conf << EOF
systemLog:
  destination: file
  path: /mongodb/38018/log/mongodb.conf
  logAppend: true
storage:
  journal:
    enabled: true
  dbPath: /mongodb/38018/data
  directoryPerDB: true
  #engine: wiredTiger
  wiredTiger:
    engineConfig:
      cacheSizeGB: 1
      directoryForIndexes: true
    collectionConfig:
      blockCompressor: zlib
    indexConfig:
      prefixCompression: true
net:
  port: 38018
replication:
  oplogSizeMB: 2048
  replSetName: configReplSet
sharding:
  clusterRole: configsvr
processManagement: 
  fork: true
EOF

cp /mongodb/38018/conf/mongodb.conf /mongodb/38019/conf/
cp /mongodb/38018/conf/mongodb.conf /mongodb/38020/conf/
sed 's#38018#38019#g' /mongodb/38019/conf/mongodb.conf -i
sed 's#38018#38020#g' /mongodb/38020/conf/mongodb.conf -i


# 3啓動節點,並配置複製集


mongod -f /mongodb/38018/conf/mongodb.conf 
mongod -f /mongodb/38019/conf/mongodb.conf 
mongod -f /mongodb/38020/conf/mongodb.conf 


mongo --port 38018
use  admin

config = {_id: 'configReplSet', members: [
                          {_id: 0, host: '10.0.0.200:38018'},
                          {_id: 1, host: '10.0.0.200:38019'},
                          {_id: 2, host: '10.0.0.200:38020'}]
           }
rs.initiate(config)  
  
  
# 注:configserver 能夠是一個節點,官方建議複製集。configserver不能有arbiter。
# 新版本中,要求必須是複製集。
# 注:mongodb 3.4以後,雖然要求config server爲replica set,可是不支持arbiter
=============================================================================
# mongos節點配置:
# 1.建立目錄:
mkdir -p /mongodb/38017/conf  /mongodb/38017/log 


# 2.配置文件:
cat >> /mongodb/38017/conf/mongos.conf <<EOF
systemLog:
  destination: file
  path: /mongodb/38017/log/mongos.log
  logAppend: true
net:
  port: 38017
sharding:
  configDB: configReplSet/10.0.0.200:38018,10.0.0.200:38019,10.0.0.200:38020
processManagement: 
  fork: true
EOF

# 3啓動mongos
mongos -f /mongodb/38017/conf/mongos.conf 

# 除了mongos知道有config之外,都沒有任何聯繫
# 分片集羣操做:

# 鏈接到其中一個mongos(10.0.0.200),作如下配置
# 1.鏈接到mongs的admin數據庫
su - mongod
mongo 10.0.0.200:38017/admin

# 2.添加分片
db.runCommand( { addshard : "sh1/10.0.0.200:38021,10.0.0.200:38022,10.0.0.200:38023",name:"shard1"} )
db.runCommand( { addshard : "sh2/10.0.0.200:38024,10.0.0.200:38025,10.0.0.200:38026",name:"shard2"} )


# 3.列出分片
mongos> db.runCommand( { listshards : 1 } )
  
  
# 4.總體狀態查看
mongos> sh.status();

# 如今都搭建好了,除了分片功能之外

5.配置Hash分片

# 對oldguo庫下的vast大表進行hash

# 建立哈希索引
# 1.對於oldguo開啓分片功能
# 首先鏈接到mongos
mongo --port 38017 admin
use admin
admin> db.runCommand( { enablesharding : "oldguo" } )

# 2.對於oldguo庫下的vast表創建hash索引
use oldguo
oldguo> db.vast.ensureIndex( { id: "hashed" } )

# 3.開啓分片 
use admin
admin > sh.shardCollection( "oldguo.vast", { id: "hashed" } )

# 4.錄入10w行數據測試
use oldguo
for(i=1;i<=100000;i++){ db.vast.insert({"id":i,"name":"shenzheng","age":70,"date":new Date()}); }

# 5.hash分片結果測試
mongo --port 38021
use oldguo
db.vast.count();

mongo --port 38024
use oldguo
db.vast.count();


# 6.判斷是否Shard集羣
admin> db.runCommand({ isdbgrid : 1})

# 7.列出全部分片信息
admin> db.runCommand({ listshards : 1})

# 8.列出開啓分片的數據庫
admin> use config

config> db.databases.find( { "partitioned": true } )
或者:
config> db.databases.find() //列出全部數據庫分片狀況

# 9.查看分片的片鍵
config> db.collections.find().pretty()
{
    "_id" : "test.vast",
    "lastmodEpoch" : ObjectId("58a599f19c898bbfb818b63c"),
    "lastmod" : ISODate("1970-02-19T17:02:47.296Z"),
    "dropped" : false,
    "key" : {
        "id" : 1
    },
    "unique" : false
}

# 10.查看分片的詳細信息
admin> db.printShardingStatus()
或
admin> sh.status()

# 11.刪除分片節點(謹慎)
(1)確認blance是否在工做
sh.getBalancerState()

(2)刪除shard2節點(謹慎)
mongos> db.runCommand( { removeShard: "shard2" } )

注意:刪除操做必定會當即觸發blancer。

7、備份

一、備份恢復工具介紹

  • mongoexport/mongoimport
JSON雖然具備較好的跨版本通用性,但其只保留了數據部分,不保留索引,帳戶等其餘基礎信息。使用時應該注意。跨平臺時推薦使用csv格式,csv是幾乎全部的數據庫都支持的格式
  • mongodump/mongorestore
導入/導出的是BSON格式。
    
    BSON則是二進制文件,體積小但對人類幾乎沒有可讀性。
    
    在一些mongodb版本之間,BSON格式可能會隨版本不一樣而有所不一樣,因此不一樣版本之間用mongodump/mongorestore可能不會成功,具體要看版本之間的兼容性。當沒法使用BSON進行跨版本的數據遷移的時候,使用JSON格式即mongoexport/mongoimport是一個可選項。

2.導出/mongoexport

Mongodb中的mongoexport工具能夠把一個collection導出成JSON格式或CSV格式的文件。JSON可讀性強但體積較大。
    能夠經過參數指定導出的數據項,也能夠根據指定的條件導出數據。
特色:
(1)版本差別較大
(2)異構平臺數據遷移

# 語法
mongoexport --help  
參數說明:
-h:指明數據庫宿主機的IP

-u:指明數據庫的用戶名

-p:指明數據庫的密碼

-d:指明數據庫的名字

-c:指明collection的名字

-f:指明要導出那些列

-o:指明到要導出的文件名

-q:指明導出數據的過濾條件

--authenticationDatabase:驗證庫
    
# 1.單表備份至json格式
mongoexport -uroot -proot123 --port 27017 --authenticationDatabase admin -d oldguo -c log -o /mongodb/log.json


# 注:備份文件的名字能夠自定義,默認導出了JSON格式的數據。

# 2. 單表備份至csv格式
# 若是咱們須要導出CSV格式的數據,則須要使用----type=csv參數:

mongoexport -uroot -proot123 --port 27017 --authenticationDatabase admin -d oldguo -c log --type=csv -f uid,name,age,date  -o /mongodb/log.csv

3.導入/mongoimport

Mongodb中的mongoimport工具能夠把一個特定格式文件中的內容導入到指定的collection中。該工具能夠導入JSON格式數據,也能夠導入CSV格式數據。具體使用以下所示:
    
$ mongoimport --help
# 參數說明:
-h:指明數據庫宿主機的IP

-u:指明數據庫的用戶名

-p:指明數據庫的密碼

-d:指明數據庫的名字

-c:指明collection的名字

-f:指明要導入那些列

-j, --numInsertionWorkers=<number>  number of insert operations to run concurrently                                                  (defaults to 1)


# 數據恢復:
# 1.恢復json格式表數據到log1,
mongoimport -uroot -proot123 --port 27017 --authenticationDatabase admin -d oldguo -c log1 /mongodb/log.json


# 2.恢復csv格式的文件到log2
上面演示的是導入JSON格式的文件中的內容,若是要導入CSV格式文件中的內容,則須要經過--type參數指定導入格式,具體以下所示:

(1)csv格式的文件頭行,有列名字
# --headerline:指明第一行是列名,不須要導入。
# csv導出是第一行是列名,因此導入時要特別注意第一行不能做爲數據導入
mongoimport   -uroot -proot123 --port 27017 --authenticationDatabase admin   -d oldguo -c log2 --type=csv --headerline --file  /mongodb/log.csv

(2)csv格式的文件頭行,沒有列名字
mongoimport   -uroot -proot123 --port 27017 --authenticationDatabase admin   -d oldguo -c log3 --type=csv -f id,name,age,date --file  /mongodb/log1.csv

4.異構平臺遷移

# mysql   -----> mongodb  
# world數據庫下city表進行導出,導入到mongodb

# 1.mysql開啓安全路徑
# 經過secure_file_priv 來完成對導入|導出的限制
# 限制mysqld 的導入 | 導出 只能發生在/tmp/目錄下
vim /etc/my.cnf   --->添加如下配置
secure-file-priv=/tmp

# 重啓數據庫生效
/etc/init.d/mysqld restart

# 2.導出mysql的city表數據
source /root/world.sql

select * from world.city into outfile '/tmp/city1.csv' fields terminated by ',';

# 3.處理備份文件
# 添加第一行列名信息
vim /tmp/city.csv   
ID,Name,CountryCode,District,Population

# 4.在mongodb中導入備份
mongoimport -uroot -proot123 --port 27017 --authenticationDatabase admin -d world  -c city --type=csv -f ID,Name,CountryCode,District,Population --file  /tmp/city1.csv

8、mongodbAPI

# 單機連接
from pymongo import MongoClient
conn = MongoClient('localhost', 27017)
client = MongoClient('mongodb://localhost:27017/')


# 複製集 replication set 連接
from pymongo import MongoReplicaSetClient
conn = MongoReplicaSetClient("10.0.0.200:28017,10.0.0.200:28018,10.0.0.200:28019", replicaset='my_repl')
# replicaset:複製集主機名
print (conn)
print (conn.primary)
print (conn.seeds)
print (conn.secondaries)
print (conn.read_preference)
print (conn.server_info())




# 分片集羣
conn = pymongo.Connection('192.168.1.1', 27017)
db = conn['test'] #假定名爲test的db已經存在
db_admin = conn['admin'] #command的執行必須經過名爲admin的db才能進行
col_data = db["data"]
for i in range(1, 50):
     col_data.insert({'_id':i, 'value':(i*200)}) #插入測試數據,必須在分片以前保證shard key的存在,本例中爲_id

db_admin.command('enablesharding', 'test') #確認目標db的sharding功能開啓(這行代碼一個數據庫只執行一次有效,若是已經設置,則會拋出異常)
db_admin.command('shardcollection', 'test.data', key = {'_id':1}) #指定目標collection和對應的shard key(這行一個表執行一次,若是出現多表,表名不一樣的狀況下,應該每張表都執行一次)
conn.close()



# 如何查看已經分片成功:
    在linux中進入mongo命令界面,
    use test
    db.test.data.stats()
    會打印出分片信息。
而且shard key能夠指定多個,同創建複合索引相似:
db_admin.command('shardcollection', 'test.data', key = {'_id':1, 'a':1, 'b':1})
相關文章
相關標籤/搜索