分片是數據跨多台機器存儲,MongoDB使用分片來支持具有非常大的數據集和高吞吐量操作的部署。 具有大型數據集或高吞吐量應用程式的資料庫系統可能會挑戰單個伺服器的容量。例如,高查詢率會耗盡伺服器的CPU容量。工作集大小大於系統的RAM會強調磁碟驅動器的I / O容量。 有兩種解決系統增長的方法:垂直 ...
分片是數據跨多台機器存儲,MongoDB使用分片來支持具有非常大的數據集和高吞吐量操作的部署。
具有大型數據集或高吞吐量應用程式的資料庫系統可能會挑戰單個伺服器的容量。例如,高查詢率會耗盡伺服器的CPU容量。工作集大小大於系統的RAM會強調磁碟驅動器的I / O容量。
有兩種解決系統增長的方法:垂直和水平縮放。
垂直擴展涉及增加單個伺服器的容量,例如使用更強大的CPU,添加更多RAM或增加存儲空間量。可用技術的局限性可能會限制單個機器對於給定工作負載而言足夠強大。此外,基於雲的提供商基於可用的硬體配置具有硬性上限。結果,垂直縮放有實際的最大值。
水平擴展涉及劃分系統數據集並載入多個伺服器,添加其他伺服器以根據需要增加容量。雖然單個機器的總體速度或容量可能不高,但每台機器處理整個工作負載的子集,可能提供比單個高速大容量伺服器更高的效率。擴展部署容量只需要根據需要添加額外的伺服器,這可能比單個機器的高端硬體的總體成本更低。權衡是基礎架構和部署維護的複雜性增加。
MongoDB支持通過分片進行水平擴展。
一、組件
- shard:每個分片包含分片數據的子集。每個分片都可以部署為副本集(replica set)。可以分片,不分片的數據存於主分片伺服器上。部署為3成員副本集
- mongos:mongos充當查詢路由器,提供客戶端應用程式和分片集群之間的介面。可以部署多個mongos路由器。部署1個或者多個mongos
- config servers:配置伺服器存儲群集的元數據和配置設置。從MongoDB 3.4開始,必須將配置伺服器部署為3成員副本集
註意:應用程式或者客戶端必須要連接mongos才能與集群的數據進行交互,永遠不應連接到單個分片以執行讀取或寫入操作。
shard的replica set的架構圖:
config servers的replica set的架構圖:
分片策略
1、散列分片
- 使用散列索引在共用群集中分區數據。散列索引計算單個欄位的哈希值作為索引值; 此值用作分片鍵。
- 使用散列索引解析查詢時,MongoDB會自動計算哈希值。應用程式也不會需要計算哈希值。
- 基於散列值的數據分佈有助於更均勻的數據分佈,尤其是在分片鍵單調變化的數據集中。
2、範圍分片
- 基於分片鍵值將數據分成範圍。然後根據分片鍵值為每個塊分配一個範圍。
- mongos可以將操作僅路由到包含所需數據的分片。
- 分片鍵的規劃很重要,可能導致數據不能均勻分佈。
二、部署
1、環境說明
伺服器名稱 | IP地址 | 操作系統版本 | MongoDB版本 | 配置伺服器(Config Server)埠 | 分片伺服器1(Shard Server 1 | 分片伺服器2(Shard Server 2) | 分片伺服器3(Shard Server 3) | 功能 |
mongo1.example.net | 10.10.18.10 | Centos7.5 | 4.0 | 27027(Primary) | 27017(Primary) | 27018(Arbiter) | 27019(Secondary) | 配置伺服器和分片伺服器 |
mongo2.example.net | 10.10.18.11 | Centos7.5 | 4.0 | 27027(Secondary) | 27017(Secondary) |
27018(Primary) | 27019(Arbiter) | 配置伺服器和分片伺服器 |
mongo3.example.net | 10.10.18.12 | Centos7.5 | 4.0 | 27027(Secondary) | 27017(Arbiter) | 27018(Secondary) | 27019(Primary) | 配置伺服器和分片伺服器 |
mongos.example.net | 192.168.11.10 | Centos7.5 | 4.0 | mongos的埠:27017 | mongos |
官方推薦配置中使用邏輯DNS,所以該文檔中,將伺服器名稱和IP地址的DNS映射關係寫入到各伺服器的/etc/hosts文件中。
2、部署MongoDB
環境中4台伺服器的MongoDB的安裝部署,詳見:MongoDB安裝
創建環境需要的目錄:
mkdir -p /data/mongodb/data/{configServer,shard1,shard2,shard3} mkdir -p /data/mongodb/{log,pid}
3、創建配置伺服器(Config Server)的 Replica Set(副本集)
3台伺服器上配置文件內容: /data/mongodb/configServer.conf
mongo1.example.net伺服器上
systemLog: destination: file path: "/data/mongodb/log/configServer.log" logAppend: true storage: dbPath: "/data/mongodb/data/configServer" journal: enabled: true wiredTiger: engineConfig: cacheSizeGB: 2 processManagement: fork: true pidFilePath: "/data/mongodb/pid/configServer.pid" net: bindIp: mongo1.example.net port: 27027 replication: replSetName: cs0 sharding: clusterRole: configsvr
mongo2.example.net伺服器上
systemLog: destination: file path: "/data/mongodb/log/configServer.log" logAppend: true storage: dbPath: "/data/mongodb/data/configServer" journal: enabled: true wiredTiger: engineConfig: cacheSizeGB: 2 processManagement: fork: true pidFilePath: "/data/mongodb/pid/configServer.pid" net: bindIp: mongo2.example.net port: 27027 replication: replSetName: cs0 sharding: clusterRole: configsvr
mongo3.example.net伺服器上
systemLog: destination: file path: "/data/mongodb/log/configServer.log" logAppend: true storage: dbPath: "/data/mongodb/data/configServer" journal: enabled: true wiredTiger: engineConfig: cacheSizeGB: 2 processManagement: fork: true pidFilePath: "/data/mongodb/pid/configServer.pid" net: bindIp: mongo3.example.net port: 27027 replication: replSetName: cs0 sharding: clusterRole: configsvr
啟動三台伺服器Config Server
mongod -f /data/mongodb/configServer.conf
連接到其中一個Config Server
mongo --host mongo1.example.net --port 27027
結果:
1 MongoDB shell version v4.0.10 2 connecting to: mongodb://mongo1.example.net:27027/?gssapiServiceName=mongodb 3 Implicit session: session { "id" : UUID("1a4d4252-11d0-40bb-90da-f144692be88d") } 4 MongoDB server version: 4.0.10 5 Server has startup warnings: 6 2019-06-14T14:28:56.013+0800 I CONTROL [initandlisten] 7 2019-06-14T14:28:56.013+0800 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database. 8 2019-06-14T14:28:56.013+0800 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted. 9 2019-06-14T14:28:56.013+0800 I CONTROL [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended. 10 2019-06-14T14:28:56.013+0800 I CONTROL [initandlisten] 11 2019-06-14T14:28:56.013+0800 I CONTROL [initandlisten] 12 2019-06-14T14:28:56.013+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'. 13 2019-06-14T14:28:56.013+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 14 2019-06-14T14:28:56.014+0800 I CONTROL [initandlisten] 15 2019-06-14T14:28:56.014+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'. 16 2019-06-14T14:28:56.014+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 17 2019-06-14T14:28:56.014+0800 I CONTROL [initandlisten] 18 >View Code
配置Replica Set
rs.initiate( { _id: "cs0", configsvr: true, members: [ { _id : 0, host : "mongo1.example.net:27027" }, { _id : 1, host : "mongo2.example.net:27027" }, { _id : 2, host : "mongo3.example.net:27027" } ] } )
結果:
1 { 2 "ok" : 1, 3 "operationTime" : Timestamp(1560493908, 1), 4 "$gleStats" : { 5 "lastOpTime" : Timestamp(1560493908, 1), 6 "electionId" : ObjectId("000000000000000000000000") 7 }, 8 "lastCommittedOpTime" : Timestamp(0, 0), 9 "$clusterTime" : { 10 "clusterTime" : Timestamp(1560493908, 1), 11 "signature" : { 12 "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), 13 "keyId" : NumberLong(0) 14 } 15 } 16 }View Code
查看Replica Set的狀態
cs0:PRIMARY> rs.status()
結果: 可以看出三個伺服器:1個Primary,2個Secondary
1 { 2 "set" : "cs0", 3 "date" : ISODate("2019-06-14T06:33:31.348Z"), 4 "myState" : 1, 5 "term" : NumberLong(1), 6 "syncingTo" : "", 7 "syncSourceHost" : "", 8 "syncSourceId" : -1, 9 "configsvr" : true, 10 "heartbeatIntervalMillis" : NumberLong(2000), 11 "optimes" : { 12 "lastCommittedOpTime" : { 13 "ts" : Timestamp(1560494006, 1), 14 "t" : NumberLong(1) 15 }, 16 "readConcernMajorityOpTime" : { 17 "ts" : Timestamp(1560494006, 1), 18 "t" : NumberLong(1) 19 }, 20 "appliedOpTime" : { 21 "ts" : Timestamp(1560494006, 1), 22 "t" : NumberLong(1) 23 }, 24 "durableOpTime" : { 25 "ts" : Timestamp(1560494006, 1), 26 "t" : NumberLong(1) 27 } 28 }, 29 "lastStableCheckpointTimestamp" : Timestamp(1560493976, 1), 30 "members" : [ 31 { 32 "_id" : 0, 33 "name" : "mongo1.example.net:27027", 34 "health" : 1, 35 "state" : 1, 36 "stateStr" : "PRIMARY", 37 "uptime" : 277, 38 "optime" : { 39 "ts" : Timestamp(1560494006, 1), 40 "t" : NumberLong(1) 41 }, 42 "optimeDate" : ISODate("2019-06-14T06:33:26Z"), 43 "syncingTo" : "", 44 "syncSourceHost" : "", 45 "syncSourceId" : -1, 46 "infoMessage" : "could not find member to sync from", 47 "electionTime" : Timestamp(1560493919, 1), 48 "electionDate" : ISODate("2019-06-14T06:31:59Z"), 49 "configVersion" : 1, 50 "self" : true, 51 "lastHeartbeatMessage" : "" 52 }, 53 { 54 "_id" : 1, 55 "name" : "mongo2.example.net:27027", 56 "health" : 1, 57 "state" : 2, 58 "stateStr" : "SECONDARY", 59 "uptime" : 102, 60 "optime" : { 61 "ts" : Timestamp(1560494006, 1), 62 "t" : NumberLong(1) 63 }, 64 "optimeDurable" : { 65 "ts" : Timestamp(1560494006, 1), 66 "t" : NumberLong(1) 67 }, 68 "optimeDate" : ISODate("2019-06-14T06:33:26Z"), 69 "optimeDurableDate" : ISODate("2019-06-14T06:33:26Z"), 70 "lastHeartbeat" : ISODate("2019-06-14T06:33:29.385Z"), 71 "lastHeartbeatRecv" : ISODate("2019-06-14T06:33:29.988Z"), 72 "pingMs" : NumberLong(0), 73 "lastHeartbeatMessage" : "", 74 "syncingTo" : "mongo1.example.net:27027", 75 "syncSourceHost" : "mongo1.example.net:27027", 76 "syncSourceId" : 0, 77 "infoMessage" : "", 78 "configVersion" : 1 79 }, 80 { 81 "_id" : 2, 82 "name" : "mongo3.example.net:27027", 83 "health" : 1, 84 "state" : 2, 85 "stateStr" : "SECONDARY", 86 "uptime" : 102, 87 "optime" : { 88 "ts" : Timestamp(1560494006, 1), 89 "t" : NumberLong(1) 90 }, 91 "optimeDurable" : { 92 "ts" : Timestamp(1560494006, 1), 93 "t" : NumberLong(1) 94 }, 95 "optimeDate" : ISODate("2019-06-14T06:33:26Z"), 96 "optimeDurableDate" : ISODate("2019-06-14T06:33:26Z"), 97 "lastHeartbeat" : ISODate("2019-06-14T06:33:29.384Z"), 98 "lastHeartbeatRecv" : ISODate("2019-06-14T06:33:29.868Z"), 99 "pingMs" : NumberLong(0), 100 "lastHeartbeatMessage" : "", 101 "syncingTo" : "mongo1.example.net:27027", 102 "syncSourceHost" : "mongo1.example.net:27027", 103 "syncSourceId" : 0, 104 "infoMessage" : "", 105 "configVersion" : 1 106 } 107 ], 108 "ok" : 1, 109 "operationTime" : Timestamp(1560494006, 1), 110 "$gleStats" : { 111 "lastOpTime" : Timestamp(1560493908, 1), 112 "electionId" : ObjectId("7fffffff0000000000000001") 113 }, 114 "lastCommittedOpTime" : Timestamp(1560494006, 1), 115 "$clusterTime" : { 116 "clusterTime" : Timestamp(1560494006, 1), 117 "signature" : { 118 "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), 119 "keyId" : NumberLong(0) 120 } 121 } 122 }View Code
創建管理用戶
use admin db.createUser( { user: "myUserAdmin", pwd: "abc123", roles: [{ role: "userAdminAnyDatabase", db: "admin" },"readWriteAnyDatabase"] } )
開啟Config Server的登錄驗證和內部驗證
使用Keyfiles進行內部認證,在其中一臺伺服器上創建Keyfiles
openssl rand -base64 756 > /data/mongodb/keyfile chmod 400 /data/mongodb/keyfile
將這個keyfile文件分發到其它的三台伺服器上,並保證許可權400
/data/mongodb/configServer.conf 配置文件中開啟認證
security: keyFile: "/data/mongodb/keyfile" clusterAuthMode: "keyFile" authorization: "enabled"
然後依次關閉2個Secondary,在關閉 Primary
mongod -f /data/mongodb/configServer.conf --shutdown
依次開啟Primary和兩個Secondary
mongod -f /data/mongodb/configServer.conf
使用用戶密碼登錄mongo
mongo --host mongo1.example.net --port 27027 -u myUserAdmin --authenticationDatabase "admin" -p 'abc123'
註意:由於剛創建用戶的時候沒有給該用戶管理集群的許可權,所有此時登錄後,能查看所有資料庫,但是不能查看集群的狀態信息。
1 cs0:PRIMARY> rs.status() 2 { 3 "operationTime" : Timestamp(1560495861, 1), 4 "ok" : 0, 5 "errmsg" : "not authorized on admin to execute command { replSetGetStatus: 1.0, lsid: { id: UUID(\"59dd4dc0-b34f-43b9-a341-a2f43ec1dcfa\") }, $clusterTime: { clusterTime: Timestamp(1560495849, 1), signature: { hash: BinData(0, A51371EC5AA54BB1B05ED9342BFBF03CBD87F2D9), keyId: 6702270356301807629 } }, $db: \"admin\" }", 6 "code" : 13, 7 "codeName" : "Unauthorized", 8 "$gleStats" : { 9 "lastOpTime" : Timestamp(0, 0), 10 "electionId" : ObjectId("7fffffff0000000000000002") 11 }, 12 "lastCommittedOpTime" : Timestamp(1560495861, 1), 13 "$clusterTime" : { 14 "clusterTime" : Timestamp(1560495861, 1), 15 "signature" : { 16 "hash" : BinData(0,"3UkTpXxyU8WI1TyS+u5vgewueGA="), 17 "keyId" : NumberLong("