一、分片
分片是一種跨多臺機器分發數據的方法。MongoDB使用分片來支持具有非常大的數據集和高吞吐量操作的部署。
問題:
具有大型數據集或高吞吐量應用程序的數據庫系統可能會挑戰單個服務器的容量。例如,高查詢率會耗盡服務器的CPU容量。工作集大小大于系統的RAM會強調磁盤驅動器的I / O容量。
解決系統增長的方法有兩種:垂直和水平縮放。
垂直擴展涉及增加單個服務器的容量,例如使用更強大的CPU,添加更多RAM或增加存儲空間量。可用技術的局限性可能會限制單個機器對于給定工作負載而言足夠強大。此外,基于云的提供商基于可用的硬件配置具有硬性上限。結果,垂直縮放有實際的最大值。
水平擴展涉及劃分系統數據集并加載多個服務器,添加其他服務器以根據需要增加容量。雖然單個機器的總體速度或容量可能不高,但每臺機器處理整個工作負載的子集,可能提供比單個高速大容量服務器更高的效率。擴展部署容量只需要根據需要添加額外的服務器,這可能比單個機器的高端硬件的總體成本更低。權衡是基礎架構和部署維護的復雜性增加。
MongoDB支持通過分片進行水平擴展
二、分片集群概述
MongoDB分片群集包含以下組件:
分片:是一個獨立普通的mongod進程,保存數據信息。可以是一個副本集也可以是單獨的一臺服務器。
mongos:起到一個路由的功能,供程序連接。本身不保存數據,在啟動時從配置服務器加載集群信息,開啟mongos進程需要知道配置服務器的地址,指定configdb選項。
配置服務器:是一個獨立的mongod進程,保存集群和分片的元數據,即各分片包含了哪些數據的信息。最先開始建立,啟用日志功能。像啟動普通的mongod一樣啟動配置服務器,指定configsvr選項。不需要太多的空間和資源,配置服務器的1KB空間相當于真是數據的200MB。保存的只是數據的分布表。當服務不可用,則變成只讀,無法分塊、遷移數據。
交互圖如下:
MongoDB在集合級別對數據進行分片,將集合數據分布在集群中的分片上。
1、鎖片鍵
為了在集合中分發文檔,MongoDB 使用分片鍵對集合進行分區。分片鍵 由目標集合中每個文檔中存在的不可變字段組成。
在分片集合時選擇分片鍵。分片后無法更改分片鍵的選擇。分片集合只能有一個分片 鍵。要對非空集合進行分片,集合必須具有 以分片鍵開頭的索引。對于空集合,如果集合尚未具有指定分片鍵的適當索引,MongoDB將創建索引。
分片鍵的選擇會影響分片群集的性能,效率和可伸縮性。具有最佳硬件和基礎結構的群集可能會因選擇分片鍵而受到瓶頸。選擇分片鍵及其支持索引也會影響群集可以使用的分片策略。
2、大塊
MongoDB將分片數據劃分為塊。每個塊都具有基于分片鍵的包含較低且獨占的較高范圍 。
3、平衡器和偶數塊分配
為了在群集中的所有分片上實現塊的均勻分布,平衡器在后臺運行以跨分片遷移塊。
4、Sharding的優點
(1)讀寫
MongoDB的分布在整個的讀寫工作量 碎片將在分片集群,使每個碎片來處理群集操作的一個子集。通過添加更多分片,可以在群集中水平擴展讀取和寫入工作負載。
對于包含分片鍵或復合分片鍵前綴mongos的查詢,可以在特定分片或分片集上定位查詢。這些目標操作通常比向群集中的每個分片廣播更有效 。
(2)存儲容量
拆分分配整個數據碎片集群中,允許每個碎片以包含總簇數據的子集。隨著數據集的增長,額外的分片會增加群集的存儲容量。
(3)高可用性
分片簇可以繼續執行,即使一個或多個碎片是不可用的部分讀/寫操作。雖然在停機期間無法訪問不可用分片上的數據子集,但是針對可用分片的讀取或寫入仍然可以成功。
備注:
(1)從MongoDB 3.2開始,您可以將配置服務器部署為副本集。只要大多數副本集可用,具有配置服務器副本集(CSRS)的分片群集就可以繼續處理讀取和寫入。
(2)在3.4版本中,MongoDB 刪除了對SCCC配置服務器的支持。
(3)在生產環境中,應將各個分片部署為 副本集,從而提供更高的冗余和可用性。
5、分片集群注意事項
(1)分片集群基礎架構要求和復雜性需要仔細規劃,執行和維護。
(2)選擇分片密鑰時需要認真考慮,以確保集群性能和效率。分片后不能更改分片鍵,也不能取消分片分片。
(3)Sharding具有一定的操作要求和限制。
(4)如果查詢不包括分片鍵或復合分片鍵的前綴 ,則mongos執行廣播操作,查詢分 片群集中的所有分片。這些分散/收集查詢可以是長時間運行的操作。
6、分片策略
MongoDB支持兩種分片策略,用于跨分片群集分發數據。
(1)散列分片
散列分片涉及計算分片鍵字段值的散列。然后,基于散列的分片鍵值為每個塊分配一個范圍。
(2)遠程分片
遠程分片涉及基于分片鍵值將數據劃分為范圍。然后根據分片鍵值為每個塊分配一個范圍
7、 MongoDB Sharding Cluster角色
(1) Shard Server
即存儲實際數據的分片每個Shard 可以是一個mongod 實例也可以是一組mongod 實例
構成的Replica Set。為了實現每個Shard 內部的auto-failoverMongoDB 官方建議每個Shard
為一組Replica Set。
(2)Config Server
為了將一個特定的collection 存儲在多個shard 中需要為該collection 指定一個shard key
例如{age: 1} shard key 可以決定該條記錄屬于哪個chunk。Config Servers 就是用來存儲
所有shard 節點的配置信息、每個chunk 的shard key 范圍、chunk 在各shard 的分布情況、
該集群中所有DB 和collection 的sharding 配置信息。
(3)Route Process
這是一個前端路由客戶端由此接入然后詢問Config Servers 需要到哪個Shard 上查詢或
保存記錄再連接相應的Shard 進行操作最后將結果返回給客戶端。客戶端只需要將原本
發給mongod 的查詢或更新請求原封不動地發給Routing Process而不必關心所操作的記錄
存儲在哪個Shard 上。
三、分配集群搭建
1、環境準備
(1)、數據庫環境
主機名 | 數據庫IP地址 | 數據庫版本 | 用途 | 系統 |
SQL_mongdb | 172.169.18.128 | mongodb4.0.3 | 配置3,路由1,分片2 | cenots7.4 |
node01 | 172.169.18.162 | mongodb4.0.3 | 路由1,分片2 | centos7.4 |
node01 | 172.169.18.180 | mongodb4.0.3 | 分片2 | centos7.4 |
(2)暫時關閉防火墻和seliunx,測試完畢再開啟安全規則
(3)yum安裝mongdb4.0版本(省略)
同樣的,在node01和node02上安裝服務
在部署之前先明白片鍵的意義,一個好的片鍵對分片至關重要。片鍵必須是一個索引,數據根據這個片鍵進行拆分分散。通過sh.shardCollection加會自動創建索引。一個自增的片鍵對寫入和數據均勻分布就不是很好,因為自增的片鍵總會在一個分片上寫入,后續達到某個閥值可能會寫到別的分片。但是按照片鍵查詢會非常高效。隨機片鍵對數據的均勻分布效果很好。注意盡量避免在多個分片上進行查詢。在所有分片上查詢,mongos會對結果進行歸并排序。
(4)
框架圖
2、配置服務器的啟動。(SQL_mongdb上開啟3個,Port:21000、22000、2300)
備注:配置服務器必須開啟1個或則3個,開啟2個則會報錯:
(1)創建目錄
[root@SQL_mongdb /]# mkdir -p /opt/mongodb/date1
[root@SQL_mongdb /]# mkdir -p /opt/mongodb/date2
[root@SQL_mongdb /]# mkdir -p /opt/mongodb/date3
(2)新建配置文件
[root@SQL_mongdb ~]# cat /etc/mongodb_21000.conf
#數據目錄
dbpath=/opt/mongodb/date1/
#日志文件
logpath=/opt/mongodb/mongodb_21000.log
#日志追加
logappend=true
#端口
port = 21000
#最大連接數
maxConns = 50
pidfilepath = /opt/mongodb/mongo_21000.pid
#日志,redo log
journal = true
#刷寫提交機制
journalCommitInterval = 200
#守護進程模式
fork = true
#刷寫數據到日志的頻率
syncdelay = 60
#storageEngine = wiredTiger
#操作日志,單位M
oplogSize = 1000
#命名空間的文件大小,默認16M,最大2G。
nssize = 16
noauth = true
unixSocketPrefix = /tmp
configsvr = true
replSet=jiangjj
bind_ip = 172.169.18.128
[root@SQL_mongdb ~]# cat /etc/mongodb_22000.conf
#數據目錄
dbpath= /opt/mongodb/date2/
#日志文件
logpath= /opt/mongodb/mongodb_22000.log
#日志追加
logappend=true
#端口
port = 22000
#最大連接數
maxConns = 50
pidfilepath = /opt/mongodb/mongo_22000.pid
#日志,redo log
journal = true
#刷寫提交機制
journalCommitInterval = 200
#守護進程模式
fork = true
#刷寫數據到日志的頻率
syncdelay = 60
#storageEngine = wiredTiger
#操作日志,單位M
oplogSize = 1000
#命名空間的文件大小,默認16M,最大2G。
nssize = 16
noauth = true
unixSocketPrefix = /tmp
configsvr = true
replSet=jiangjj
bind_ip = 172.169.18.128
[root@SQL_mongdb ~]# cat /etc/mongodb_23000.conf
#數據目錄
dbpath= /opt/mongodb/date3/
#日志文件
logpath= /opt/mongodb/mongodb_23000.log
#日志追加
logappend=true
#端口
port = 23000
#最大連接數
maxConns = 50
pidfilepath = /opt/mongodb/mongo_23000.pid
#日志,redo log
journal = true
#刷寫提交機制
journalCommitInterval = 200
#守護進程模式
fork = true
#刷寫數據到日志的頻率
syncdelay = 60
#storageEngine = wiredTiger
#操作日志,單位M
oplogSize = 1000
#命名空間的文件大小,默認16M,最大2G。
nssize = 16
noauth = true
unixSocketPrefix = /tmp
configsvr = true
replSet=jiangjj
bind_ip = 172.169.18.128
(3)啟動配置文件(實例進程)
[root@SQL_mongdb ~]# mongod -f /etc/mongodb_21000.conf
[root@SQL_mongdb ~]# mongod -f /etc/mongodb_22000.conf
[root@SQL_mongdb ~]# mongod -f /etc/mongodb_23000.conf
備注:
關閉進程服務
# mongod -f /etc/mongodb_21000.conf --shutdown
如果非正常訪問,重新啟動會報錯,必須要刪除mongd.lock后才能啟動成功。
(4)將節點配置組成集群(副本集)
在任意節點啟動配置,這里使用SQL_jiangjj節點
登錄數據庫
[root@SQL_mongdb ~]# mongo --host 172.169.18.128:21000
> use admin
> cfg={ _id:"jiangjj",members:[{_id:0,host:'172.169.18.128:21000',priority:3},{_id:1,host:'172.169.18.128:22000',priority:2},{_id:2,host:'172.169.18.128:23000',priority:1}] };
#配置生效命令
> rs.initiate(cfg)
3、路由配置(在SQL_mongodb和node01上各開啟1個,port:3000)
路由服務器不保存數據,把日志記錄一下即可
(1)在SQL_mongodb上新增配置文件
[root@SQL_mongdb ~]# vim /etc/mongodb_30000.conf
#日志文件
logpath = /opt/mongodb/mongodb_route.log
#日志追加
logappend = true
#端口
port = 30000
#最大連接數
maxConns = 20000
#chunkSize=1
#綁定地址
bind_ip = 0.0.0.0
pidfilepath = /opt/mongodb/mongo_30000.pid
#必須是1個或則3個配置
configdb = jiangjj/172.169.18.128:21000,172.169.18.128:22000,172.169.18.128:23000
#configdb=127.0.0.1:20000 ?#報錯
#守護進程模式
fork = true
(2)開啟mongos
[root@SQL_mongdb ~]# mongos -f /etc/mongodb_30000.conf
(3)配置一個普通分片文件
查看狀態
按照上面的方法再到node01上開啟分片服務和路由服務(配置文件一樣),以及在node02上開啟分片服務。到此分片的配置服務器、路由服務器、分片服務器都已經部署完成。
備注:分片其中一個配置,其他的類似
[root@node01 etc]# vim mongodb_60000.conf
#mongodb
dbpath=/opt/mongodb/date2/
logpath=/opt/mongodb_60000.log
pidfilepath=/opt/mongodb/mongodb_60000.pid
directoryperdb=true
logappend=true
bind_ip=172.169.18.162
port=60000
oplogSize=100
fork=true
noprealloc=true
4、配置分片:下面的操作都是在mongodb的命令行里執行
(1)登陸路由服務器mongos 操作:
[root@SQL_mongdb ~]# mongo --port=30000
mongos> use admin
mongos> db.runCommand({addshard:'172.169.18.128:60000'})
mongos> db.runCommand({addshard:'172.169.18.162:60000'})
mongos> db.runCommand({addshard:'172.169.18.180:60000'})
#查看
mongos> sh.status()
(2)開啟分片功能:sh.enableSharding("庫名")、sh.shardCollection("庫名.集合名",{"key":1})
mongos> sh.enableSharding('jiangjj')
mongos> sh.status()
mongos> sh.shardCollection("jiangjj.text",{"name":1})
報錯如下:
Cannot accept sharding commands if not started with --shardsvr
在分片配置文件中加入如下參數:
shardsvr = true
重啟進程后執行上面的命令
查看:mongos> sh.status()
查看詳細信息:
mongos> sh.status({"verbose":1})
或則
mongos> db.printShardingStatus("vvvv")
或則
mongos> printShardingStatus(db.getSisterDB("config"),1)
#判斷是否是Sharding
5、測試查看
1、在路由Mongos端添加數據庫和數據,如此
2、添加的數據庫分配到不聽的分片節點上
備注:這里我們做的都是單點的,要是一個分片壞了,則數據會丟失,我們可以利用副本集減少災難
四、高可用:Sharding+Replset
1、在三個節點各自添加一個分片,port:50000,name:user01
其中一個集群分片,根據實際情況修改調整
#mongodb
dbpath=/opt/mongodb/date1/
logpath=/opt/mongodb_50000.log
pidfilepath=/opt/mongodb/mongodb_50000.pid
#keyFile=/opt/mongodb/mongodb.key ?//節點間用戶驗證文件,內容必須一致,權限600,僅副本集模式有效
directoryperdb=true
logappend=true
replSet=user01
bind_ip=172.169.18.162
port=50000
#auth=true
oplogSize=100
fork=true
noprealloc=true
#maxConns=4000
shardsvr = true
2、將分片設置成副本集
登錄數據庫
[root@SQL ~]# mongo --host 172.169.18.128:50000
> use admin
> user01db={ _id:"user01",members:[{_id:0,host:'172.169.18.128:50000',priority:3},{_id:1,host:'172.169.18.162:50000',priority:2},{_id:2,host:'172.169.18.180:50000',priority:1}] };
#配置生效命令
> rs.initiate(user01db)
3、配置路由節點
[root@SQL_mongdb ~]# mongo --port=30000
切換到admin庫
mongos> use admin
#添加分片節點
mongos> sh.addShard("user01/172.169.18.128:50000")
備注:
#也可以直接在路由節點添加副本集
mongos>sh.addShard("user01/172.169.18.128:50000,172.169.18.162:50000,172.169.18.180:50000")
#查看集群信息
mongos> sh.status()
補充說明:均衡器
均衡器:均衡器負責數據遷移,周期性的檢查分片是否存在不均衡,如果不存在則會開始塊的遷移,config.locks集合里的state表示均衡器是否找正在運行,0表示非活動狀態,2表示正在均衡。均衡遷移數據的過程會增加系統的負載:目標分片必須查詢源分片的所有文檔,將文檔插入目標分片中,再清除源分片的數據。可以關閉均衡器(不建議):關閉會導致各分片數據分布不均衡,磁盤空間得不到有效的利用。?
查看狀態:mongos> sh.getBalancerState()
關閉命令:mongos> sh.stopBalancer()
開啟命令:mongos> sh.setBalancerState(true)
4、在Mongos添加兩個數據庫user01和user02,添加數據測試副本集
分配在不同的分片節點上,查看的數據不同
5、分片數據庫遷移,刪除分片
刪除分片時,必須確保該分片上的數據被移動到其他分片中,對于以分片的集合,使用均衡器來遷移數據塊,對于非分片的集合,必須修改集合的主分片。
1)將shard0001分片上的數據庫jiangjj04遷移到user01集合分片上
mongos> use admin
mongos> db.runCommand({moveprimary:"jiangjj04",to:"user01"})
如下:
2、刪除分片:
#需要到admin下面刪除(需要執行兩次)
mongos> db.runCommand({"removeshard":"jiangjj01"})
注意:MongoDB的分片不能刪除最后一個,否則報如下錯誤
3、刪除分片上的數據庫
mongos> use jsqdb
mongos> db.dropDatabase()
三、集群用戶驗證設置
1、創建驗證秘鑰文件
keyFile文件的作用: 集群之間的安全認證,增加安全認證機制KeyFile(開啟keyfile認證就默認開啟了auth認證了,為了保證后面可以登錄,我已創建了用戶)
# cd /opt/mongodb/
# ?touch .keyFile
# ?chmod 600 .keyFile
# openssl rand -base64 102 > .keyFile
102:是文件大小
注意:創建keyFile前,需要先停掉副本集中所有主從節點的mongod服務,然后再創建,否則有可能出現服務啟動不了的情況。
2、在Mongos節點添加root賬號
mongos> use admin
mongos> db.createUser({
... user:'root',
... pwd:'123456',
... roles:[{role:'root',db:'admin'}]
... })
3、更新所有配置、分片節點配置文件,在路由配置文件只配置keyFile參數即可
keyFile=/home/data/.keyFile
auth=true
4、啟動副本集,測試
登錄驗證
root用戶
現在只有兩個路由節點端口30000有權訪問數據庫,其他節點訪問如下圖報錯信息
在mongos節點給jiangjj01配置用戶
添加一個jiangjj用戶擁有讀寫權限
登錄Mongos節點驗證成功。
補充知識點:
權限伸縮
1)如何增加權限
db.grantRolesToUser(
<user_name>,
[{role:<role_name>,db:<db_name>}])
注意:此方法接受2個參數,而不是兩個對象, 而且如何權限重復不會覆蓋,新的會增加
例如:
db.grantRolesToUser('roleTest,[{role:'readWrite',db:'test'}])\
2)如何收縮權限
db.revokeRolesToUser(
<user_name>,
[{role:<role_name>,db:<db_name>}])
權限配置詳細請參考官方
轉載于:https://blog.51cto.com/13941177/2309939