1、分片组件
mongo中分片由以下三个组件组成:Shard Server,Config Server,Router Server。
1.1、Shard Server
Shard Server为存储实际数据的分片,每个Shard 可以是一个mongod 实例,也可以是一组mongod 实例构成的Replica Set。为了实现每个Shard 内部的auto-failover,MongoDB 官方建议每个Shard为一组Replica Set。
分片中的每个数据库都有一个主要分片,它包含该数据库的所有未分片的集合,每个数据库都有自己的主分片,主分片与副本集中的主无关。在创建新数据库时通过选择 cluster 中具有最少数据量的分片来选择主分片。
要更改数据库的主分片,请使用movePrimary命令。迁移主分片的 process 可能需要很长时间才能完成,并且在完成之前不应访问与数据库关联的集合。根据要迁移的数据量,迁移可能会影响整个 cluster 操作。在尝试更改主分片之前,请考虑对 cluster 操作和网络负载的影响。
使用sh.status()方法可查看分片的信息,包含数据库主分片及分片中的块分布等。
1.2、Config Server
配置服务器存储分片 cluster的元数据。元数据反映了分片 cluster 中所有数据和组件的 state 和组织。元数据包括每个分片上的块列表以及定义块的范围。mongos实例缓存此数据并使用它将读取和写入操作路由到正确的分片, mongos在 cluster 的元数据更改时更新缓存,每个分片 cluster 必须有自己的配置服务器。不要将相同的配置服务器用于不同的分片群集。
分片群集的配置服务器可以部署为副本集而不是三个镜像配置服务器。使用配置服务器的副本集可以提高配置服务器之间的一致性,因为 MongoDB 可以利用配置数据的标准副本集读写协议。此外,使用配置服务器的副本集允许分片 cluster 具有 3 个以上的配置服务器,因为副本集最多可包含 50 个成员。要将配置服务器部署为副本集,配置服务器必须 run WiredTiger 存储引擎。
当副本集用于配置服务器时,有以下限制:
- 必须为零仲裁者。
- 必须没有推迟会员。
- 必须 build 索引(i.e.没有成员应将buildIndexes设置设置为 false)。
admin数据库包含与身份验证和授权相关的集合以及内部使用的其他system.*集合。配置数据库包含包含分片 cluster 元数据的集合。 MongoDB 在元数据更改时将数据写入配置数据库。
MongoDB 从admin数据库读取身份验证和授权数据以及其他内部用途。当mongos启动时或在元数据发生更改后,MongoDB 从config数据库读取。
如果所有配置服务器都不可用,则 cluster 可能无法运行。为确保配置服务器保持可用且完整,配置服务器的备份至关重要。配置服务器上的数据与存储在 cluster 中的数据相比较小,并且配置服务器的活动负载相对较低。
mongod和mongos实例会监听config服务器状态,如果联系不成功监听配置服务器副本集次数超过replMonitorMaxFailedChecks的配置值,则mongos或mongod实例将无法使用,直到重新启动实例。
1.3、Router Server
router在分片 cluster中对分片进行查询和写入操作。 mongos从客户端的角度提供了分片 cluster 的唯一接口, 用户永远不会与分片直接连接或通信。mongos通过缓存配置服务器中的元数据来跟踪哪些数据在哪个分片上。 mongos使用元数据来将 applications 和 clients 中的操作路由到mongod实例。 mongos没有持久 state 并且消耗最少的系统资源。
mongos查询处理为,确定必须接收查询的碎片列表,在所有分片上建立游标,合并来自各目标分片的数据并返回结果文档。某些查询修饰符在主分片上执行。对不包含片键的查询执行广播操作,即将查询路由到分片集群的所有分片中,同时某些包含片键的查询仍可能导致广播查询,具体取决于分片中的数据分布和查询的选择性。
mongos查询修饰符处理:
- 排序:如果未对查询结果进行排序,则mongos实例将打开一个结果游标,即从分片上的所有游标“循环”结果。
- 范围:如果查询使用limit() 方法限制结果集的大小,则mongos实例会将该限制传递给分片,然后在将结果返回给 client 之前将结果限制为 re-applies。
- 跳过:如果查询使用skip() 方法指定要跳过的记录数,则mongos无法将跳过传递给分片,而是从分片中检索未提取的结果,并在汇总完整结果时跳过适当数量的文档。
通常,分片环境中最快的查询是mongos route 到单个分片,使用配置服务器中的碎片 key和 cluster 元数据。这些目标操作使用 shard key value 来定位满足查询文档的分片或分片子集。对于不包含 shard key 的查询,mongos必须查询所有分片,等待其响应,然后_return 将结果返回到 application。这些“scatter/gather”查询可以是 long running 操作。
updateMany()和deleteMany()方法是 broadcast 操作,除非查询文档完整指定了 shard key。
mongos可以 route 查询包含 shard key 或复合 shard key 的前缀 key 特定分片或一组分片。 mongos使用 shard key来定位块,其范围包括 shard key,并将查询指向包含该块的碎片。
所有insertOne()操作都针对一个分片。 insertMany() 中的每个文档都以单个分片为目标,但不能保证 insert 中的所有文档都成为一个分片。所有updateOne(),replaceOne()和deleteOne()操作必须在查询文档中包含碎片 key或_id。如果在没有 shard key 或_id的情况下使用这些方法,则 MongoDB 会返回错误。根据 cluster 中的数据分布和查询的选择性,mongos可能仍会执行broadcast 操作来完成这些查询。
如果查询不包含碎片 key,则mongos必须将查询作为“scatter/gather”操作发送到所有分片。反过来,每个分片将使用 shard key 索引或另一个更有效的索引来完成查询。如果查询包含多个 sub-expressions,它们引用由分片 key 和辅助索引索引的字段,则mongos可以将查询路由到特定分片,并且分片将使用允许其最有效地执行的索引。
2、片键
片键确定分片中集合文件的分布情况,片键是集合中每个文档存在的索引或符合索引。mongo通过片键的范围来确定分块,一个范围的片键对应一个数据分块,片键在分块中均匀分布,片键与块分布的有效性直接相关。片键一旦确定无法更改。
2.1、片键索引
所有分片集合必须具有支持碎片 key的索引。索引可以是 shard key 上的索引,也可以是复合索引,其中 shard key 是索引的字首。如果集合为空,则sh.shardCollection()在分片 key 上创建索引(如果此类索引尚不存在)。如果集合不为空,则必须先使用sh.shardCollection()创建索引。
通过在 shard key 上使用唯一索引,MongoDB 可以对 shard key 值强制执行唯一性。 MongoDB 强制整个 key 组合的唯一性,而不是 shard key 的各个组件。要对 shard key 值强制实施唯一性,请将unique参数作为true传递给sh.shardCollection()方法:如果集合为空,则sh.shardCollection()在分片 key 上创建唯一索引(如果此类索引尚不存在)。如果集合不为空,则必须先使用sh.shardCollection()创建索引。
2.2、片键的选择
片键的选择会影响所有分片中块的创建和分布情况。这会影响分片集群中的整体效率和操作性能。理想的片键能使文档在分片中均匀分布。
片键的基数确定平衡器可以创建的最大块数,大的基数会减少或消除分片集合的水平扩容能力。在给定的时间内,唯一的片键只存在于唯一的块内。
具有高基数的分片 key 不能保证在分片 cluster 中均匀分布数据,尽管它更有利于水平扩展。 shard key 的频率和变化率也有助于数据分发。选择分片 key 时请考虑每个因素。若数据 模型需要对基数较低的 key 进行分片,请考虑使用具有较高相对基数的符合索引。
具有低频率的 shard key 不能保证在分片 cluster 中均匀分布数据。 shard key 的基数和变化率也有助于数据分发。value 上单调增加或减少的分片 key 更有可能将插入分布到 cluster 中的单个分片。发生这种情况是因为每个 cluster 都有一个块,它捕获一个上限为maxKey的范围。 maxKey始终比其他所有值都高。类似地,有一个块捕获具有minKey下限的范围。 minKey始终比较低于所有其他值。如果 shard key value 始终在增加,则所有新插入都将路由到以maxKey作为上限的块。如果 shard key value 始终在减少,则所有新插入都将路由到以minKey作为下限的块。包含该块的分片成为写操作的瓶颈。当使用单调变化的字段作为片键时,考虑使用哈希索引。
2.3、散列片键
散列分片键使用单个字段的哈希指数作为碎片 key来分割分片 cluster 中的数据。
散列分片在分片 cluster 中提供更均匀的数据分布,但代价是减少目标操作与 Broadcast Operations。使用散列分片,具有“close”分片 key 值的文档不可能在同一块或分片上,并且mongos更有可能执行Broadcast Operations来完成给定查询。
以下操作使用哈希分片策略对目标集合进行分片:
sh.shardCollection("<database>.<collection>", { <shard key> : "hashed" } )
必须指定集合的完整命名空间和 shard key。选择的 shard key 会影响分片的效率,以及利用某些分片 features(如zones)的能力。
2.4、范围片键
在 ranged-based 分片中,MongoDB 会自动将数据划分为由碎片 key值确定的连续范围。在此 model 中,具有“close”shard key 值的文档可能位于相同的块或碎片中。这允许有效查询,其中读取操作将目标文档定位在连续范围内。但是,读取和写入 performance 都可能会因为 shard key 选择不当而降低。见Shard Key Selection。
3、分片中的Chunks
MongoDB 使用与集合关联的片键将数据分区为块,块由分片数据的子集组成,mongos routes 根据碎片 key value 写入相应的块。 MongoDB 在超出配置的块大小时会分割块。插入和更新都可以触发块拆分。
3.1、块大小
MongoDB 中的默认块大小为 64 兆字节。你可以增加或减少块大小。
考虑更改默认块大小的含义:
小块以更频繁的迁移为代价导致更均匀的数据分布。这会在查询路由(mongos)层创建费用。
大块导致迁移更少。从网络角度和查询路由层的内部开销来看,这都更有效。但是,这些效率是以可能不均衡的数据分布为代价的。
块大小会影响每个要迁移的块的最大文档数。
分片现有的集合时,块大小会影响最大集合大小。 Post-sharding,块大小不会限制集合大小。
3.2、块分裂
当块增长超过指定的块大小时,或者块中的文档数超过Maximum Number of Documents Per Chunk to Migrate时,MongoDB 根据块中的 shard key 值对块进行拆分。必要时,块可以分成多个块。插入和更新可能会触发拆分。分裂是一种有效的 meta-data 变化。要创建拆分,MongoDB 不会迁移任何数据或影响分片。拆分可能导致碎片的分布不均匀,从而在分片上产生块迁移。在这种情况下,平衡器会跨分片重新分配块
3.3、块迁移
mongodb通过在分片直接迁移块来保持分片的数据均衡。迁移方式为:
- 手动:可通过命令手动进行块的迁移,以达到分片之间的数据均衡;
- 自动:当分片中数据块分布不均时,平衡器自动进行块迁移。
4、平衡器
MongoDB 平衡器是一个后台 process,用于监视每个碎片上块的数量。当给定分片上的块数达到特定迁移阈值时,平衡器会尝试在分片之间自动迁移块,并在每个分片中达到相同数量的块。 分片簇的平衡过程对用户和 application 层完全透明,尽管在执行过程时可能会产生一些性能影响。
4.1、查看平衡器状态
sh.getBalancerState()检查平衡器是否已启用(i.e.允许平衡器运行 run)。 sh.getBalancerState()不检查平衡器是否正在主动平衡块。要查看分片 cluster中是否启用了平衡器,请发出以下命令,该命令将返回 boolean:
sh.getBalancerState()
4.2、检查平衡器是否运行中
使用以下操作确定平衡器是否正在运行:
sh.isBalancerRunning()
4.3、配置默认块大小
分片 cluster 的默认块大小为 64 MB。在大多数情况下,默认大小适合拆分和迁移块。更改默认块大小会影响迁移期间进程和 auto-splits 的块,但不会追溯影响所有块。
4.4、设置平衡窗口
在某些情况下,特别是当数据集缓慢增长且迁移可能影响性能时,确保平衡器仅在特定时间处于活动状态非常有用。以下过程指定activeWindow,这是平衡器能够迁移块的时间范围,确保平衡器未停止。平衡器不会在stopped state 中激活。要确保平衡器不是stopped。
使用update()设置activeWindow,如下所示:
db.settings.update(
{ _id: "balancer" },
{ $set: { activeWindow : { start : "<start-time>", stop : "<stop-time>" } } },
{ upsert: true }
)
4.5、删除平衡窗口
使用$unset清除activeWindow,如下所示:
use config
db.settings.update({ _id : "balancer" }, { $unset : { activeWindow : true } })
4.6、禁用平衡器
默认情况下,平衡器可以在任何时间运行,并且只在需要时移动块。要在短时间内禁用平衡器并阻止所有迁移,请使用以下过程:
- 使用mongo shell 连接到 cluster 中的任何mongos。
- 发出以下操作以禁用平衡器:sh.stopBalancer();
4.7、启用平衡器
如果您已禁用平衡器并准备好 re-enable 它,请使用此过程:
使用mongo shell 连接到 cluster 中的任何mongos。
发出以下操作之一以启用平衡器:sh.setBalancerState(true)
4.8、在集合上启用/禁用平衡器
您可以使用sh.enableBalancing()方法为特定集合启用平衡。为集合启用平衡时,MongoDB 不会立即开始平衡数据。但是,如果分片集合中的数据不平衡,MongoDB 将能够更均匀地开始分发数据。要在集合上启用平衡,请使用mongo shell 连接到mongos并调用sh.enableBalancing()方法。
sh.enableBalancing("students.grades")
禁用集合上的平衡时,MongoDB 不会中断正在进行的迁移。
sh.disableBalancing("students.grades")
4.9、确定集合启用/禁用平衡器
要确认是否已启用或禁用集合的平衡,请在config数据库中查询集合命名空间的collections集合,并检查noBalance字段。例如:
db.getSiblingDB("config").collections.findOne({_id : "students.grades"}).noBalance;
此操作将返回 null 错误,true,false或无输出:
null 错误表示集合命名空间不正确。
如果结果为true,则禁用平衡。
如果结果为false,则当前启用平衡,但过去已为集合禁用了平衡。此集合的平衡将在平衡器运行的下一个 time 开始。
如果操作未返回任何输出,则当前启用平衡,并且此集合以前从未禁用过。此集合的平衡将在平衡器运行的下一个 time 开始。
5、部署分片
5.1、shard集群配置
5.1.1、分片集群目录
构造三个节点的副本集分片。
端口号为27117的节点目录:
#数据目录
C:\mongo\shard\shard_27117\data
#日志目录
C:\mongo\shard\shard_27117\log
//配置目录
C:\mongo\shard\shard_27117\config.conf
端口号为27118的目录:
#数据目录
C:\mongo\shard\shard_27118\data
#日志目录
C:\mongo\shard\shard_27118\log
//配置目录
C:\mongo\shard\shard_27118\config.conf
端口号为27119的目录:
#数据目录
C:\mongo\shard\shard_27119\data
#日志目录
C:\mongo\shard\shard_27119\log
//配置目录
C:\mongo\shard\shard_27119\config.conf
5.1.2、分片集群配置
端口号为27117节点的配置:
logpath=C:\mongo\shard\shard_27117\log\db.log
pidfilepath=C:\mongo\shard\shard_27117\mongo.pid
logappend=true
port=27117
dbpath=C:\mongo\shard\shard_27117\data
shardsvr=true # 在配置文件添加此项就行
oplogSize=512
replSet=shard
端口号为27118节点的配置:
logpath=C:\mongo\shard\shard_27118\log\db.log
pidfilepath=C:\mongo\shard\shard_27118\mongo.pid
logappend=true
port=27118
dbpath=C:\mongo\shard\shard_27118\data
shardsvr=true # 在配置文件添加此项就行
oplogSize=512
replSet=shard
端口号为27119分片的配置:
logpath=C:\mongo\shard\shard_27119\log\db.log
pidfilepath=C:\mongo\shard\shard_27119\mongo.pid
logappend=true
port=27119
dbpath=C:\mongo\shard\shard_27119\data
shardsvr=true # 在配置文件添加此项就行
oplogSize=512
replSet=shard
5.1.3、分片集群的启动
./mongod.exe --config C:\\mongo\\shard\\shard_27117\\config.conf ./mongod.exe --config C:\\mongo\\shard\\shard_27118\\config.conf ./mongod.exe --config C:\\mongo\\shard\\shard_27119\\config.conf
5.1.4、分片集群的初始化
连接一个分片副本集的一个节点:
$ ./mongo.exe --port 27117
MongoDB shell version v4.2.0
connecting to: mongodb://127.0.0.1:27117/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("f31e1cf8-82d5-4b7d-b70b-9c7db887ad3d") }
MongoDB server version: 4.2.0
副本集初始化:
use admin
switched to db admin
rsconf = { _id:"shard",members:[ {_id:0,host:"localhost:27117"}, {_id:1,host:"localhost:27118"}, {_id:2,host:"localhost:27119"}] }
{
"_id" : "shard",
"members" : [
{
"_id" : 0,
"host" : "localhost:27117"
},
{
"_id" : 1,
"host" : "localhost:27118"
},
{
"_id" : 2,
"host" : "localhost:27119"
}
]
}
rs.initiate(rsconf)
{
"operationTime" : Timestamp(1579231067, 1),
"ok" : 0,
"errmsg" : "already initialized",
"code" : 23,
"codeName" : "AlreadyInitialized",
"$clusterTime" : {
"clusterTime" : Timestamp(1579231067, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
分片副本集状态查看:
db.isMaster()
{
"hosts" : [
"localhost:27117",
"localhost:27118",
"localhost:27119"
],
"setName" : "shard",
"setVersion" : 1,
"ismaster" : true,
"secondary" : false,
"primary" : "localhost:27117",
"me" : "localhost:27117",
"electionId" : ObjectId("7fffffff0000000000000002"),
"lastWrite" : {
"opTime" : {
"ts" : Timestamp(1579231077, 1),
"t" : NumberLong(2)
},
"lastWriteDate" : ISODate("2020-01-17T03:17:57Z"),
"majorityOpTime" : {
"ts" : Timestamp(1579231077, 1),
"t" : NumberLong(2)
},
"majorityWriteDate" : ISODate("2020-01-17T03:17:57Z")
},
"maxBsonObjectSize" : 16777216,
"maxMessageSizeBytes" : 48000000,
"maxWriteBatchSize" : 100000,
"localTime" : ISODate("2020-01-17T03:18:03.873Z"),
"logicalSessionTimeoutMinutes" : 30,
"connectionId" : 17,
"minWireVersion" : 0,
"maxWireVersion" : 8,
"readOnly" : false,
"ok" : 1,
"$clusterTime" : {
"clusterTime" : Timestamp(1579231077, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
},
"operationTime" : Timestamp(1579231077, 1)
}
5.2、config副本集配置
5.2.1、config副本集目录
端口号为27217的节点:
#数据目录
C:\mongo\config\config_27217\data
#日志目录
C:\mongo\config\config_27217\log
//配置目录
C:\mongo\config\config_27217\config.conf
端口号为27218的节点
#数据目录
C:\mongo\config\config_27218\data
#日志目录
C:\mongo\config\config_27218\log
//配置目录
C:\mongo\config\config_27218\config.conf
端口号为27219的节点:
#数据目录
C:\mongo\config\config_27219\data
#日志目录
C:\mongo\config\config_27219\log
//配置目录
C:\mongo\config\config_27219\config.conf
5.2.2、三节点的配置
端口号为27117节点的配置:
logpath=C:\mongo\config\config_27217\log\db.log
pidfilepath=C:\mongo\config\config_27217\mongo.pid
logappend=true
port=27217
dbpath=C:\mongo\config\config_27217\data
configsvr=true # 在配置文件添加此项就行
oplogSize=512
replSet=config
端口号为27118节点的配置:
logpath=C:\mongo\config\config_27218\log\db.log
pidfilepath=C:\mongo\config\config_27218\mongo.pid
logappend=true
port=27218
dbpath=C:\mongo\config\config_27218\data
configsvr=true # 在配置文件添加此项就行
oplogSize=512
replSet=config
端口号为27119节点的配置:
logpath=C:\mongo\config\config_27219\log\db.log
pidfilepath=C:\mongo\config\config_27219\mongo.pid
logappend=true
port=27219
dbpath=C:\mongo\config\config_27219\data
configsvr=true # 在配置文件添加此项就行
oplogSize=512
replSet=config
5.1.3、config副本集的启动
./mongod.exe --config C:\\mongo\\config\\config_27217\\config.conf ./mongod.exe --config C:\\mongo\\config\\config_27218\\config.conf ./mongod.exe --config C:\\mongo\\config\\config_27219\\config.conf
5.1.4、副本集的初始化
连接到某个节点:
./mongo.exe --port 27217
配置初始化参数:
rsconf = {
_id: "config",
members: [{
_id: 0,
host: "localhost:27217"
}, {
_id: 1,
host: "localhost:27218"
}, {
_id: 2,
host: "localhost:27219"
}]
}
初始化副本集:
rs.initiate(rsconf)
{
"ok" : 1,
"$gleStats" : {
"lastOpTime" : Timestamp(1579168488, 1),
"electionId" : ObjectId("000000000000000000000000")
},
"lastCommittedOpTime" : Timestamp(0, 0),
"$clusterTime" : {
"clusterTime" : Timestamp(1579168488, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
},
"operationTime" : Timestamp(1579168488, 1)
}
查看副本集状态:
rs.conf()
{
"_id" : "config",
"version" : 1,
"configsvr" : true,
"protocolVersion" : NumberLong(1),
"writeConcernMajorityJournalDefault" : true,
"members" : [
{
"_id" : 0,
"host" : "localhost:27217",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 1,
"host" : "localhost:27218",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 2,
"host" : "localhost:27219",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
}
],
"settings" : {
"chainingAllowed" : true,
"heartbeatIntervalMillis" : 2000,
"heartbeatTimeoutSecs" : 10,
"electionTimeoutMillis" : 10000,
"catchUpTimeoutMillis" : -1,
"catchUpTakeoverDelayMillis" : 30000,
"getLastErrorModes" : {
},
"getLastErrorDefaults" : {
"w" : 1,
"wtimeout" : 0
},
"replicaSetId" : ObjectId("5e2032e8cf32782800b7fa3a")
}
}
rs.isMaster()
{
"hosts" : [
"localhost:27217",
"localhost:27218",
"localhost:27219"
],
"setName" : "config",
"setVersion" : 1,
"ismaster" : true,
"secondary" : false,
"primary" : "localhost:27217",
"me" : "localhost:27217",
"electionId" : ObjectId("7fffffff0000000000000001"),
"lastWrite" : {
"opTime" : {
"ts" : Timestamp(1579169171, 2),
"t" : NumberLong(1)
},
"lastWriteDate" : ISODate("2020-01-16T10:06:11Z"),
"majorityOpTime" : {
"ts" : Timestamp(1579169171, 2),
"t" : NumberLong(1)
},
"majorityWriteDate" : ISODate("2020-01-16T10:06:11Z")
},
"configsvr" : 2,
"maxBsonObjectSize" : 16777216,
"maxMessageSizeBytes" : 48000000,
"maxWriteBatchSize" : 100000,
"localTime" : ISODate("2020-01-16T10:06:28.483Z"),
"logicalSessionTimeoutMinutes" : 30,
"connectionId" : 2,
"minWireVersion" : 0,
"maxWireVersion" : 8,
"readOnly" : false,
"ok" : 1,
"$gleStats" : {
"lastOpTime" : Timestamp(1579168488, 1),
"electionId" : ObjectId("7fffffff0000000000000001")
},
"lastCommittedOpTime" : Timestamp(1579169171, 2),
"$clusterTime" : {
"clusterTime" : Timestamp(1579169171, 2),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
},
"operationTime" : Timestamp(1579169171, 2)
}
5.3、router配置
5.3.1、router的目录
C:\mongo\router\router_27017\data
C:\mongo\router\router_27017\log
C:\mongo\router\router_27017\config.conf
5.3.2、router的配置
logpath=C:\mongo\router\router_27017\db.log
pidfilepath=C:\mongo\router\router_27017mongo.pid
logappend=true
port=27017
configdb=config/127.0.0.1:27217,127.0.0.1:27218,127.0.0.1:27219
configdb中格式为<setName>/[host1:port1,host2:port2]
5.3.3、添加服务器分片
连接router:
./mongo.exe --port 27117
添加分片服务器:
mongos> db.runCommand({addshard:"shard/localhost:27117"})
{
"shardAdded" : "shard",
"ok" : 1,
"operationTime" : Timestamp(1579231179, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1579231179, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
addShard命令参数格式为:<setName>/[host1:port1,host2:port2]
5.4、对集合分片
创建数据和集合:
mongos> use dest
switched to db dest
mongos> db.createCollection("city")
{
"ok" : 1,
"operationTime" : Timestamp(1579231933, 8),
"$clusterTime" : {
"clusterTime" : Timestamp(1579231933, 8),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
mongos> db.city.createIndex({name:"code"})
{
"raw" : {
"config/localhost:27217,localhost:27218,localhost:27219" : {
"ok" : 0,
"errmsg" : "Unknown index plugin 'code'",
"code" : 67,
"codeName" : "CannotCreateIndex"
}
},
"code" : 67,
"codeName" : "CannotCreateIndex",
"ok" : 0,
"errmsg" : "Unknown index plugin 'code'",
"operationTime" : Timestamp(1579232211, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1579232211, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
设置数据及索引分片
mongos> use admin
switched to db admin
mongos> db.runCommand({ enablesharding:"dest" })
{
"ok" : 1,
"operationTime" : Timestamp(1579232062, 3),
"$clusterTime" : {
"clusterTime" : Timestamp(1579232062, 3),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
mongos> db.runCommand({ shardcollection: "dest.city", key: { code:1}})
{
"ok" : 0,
"errmsg" : "Please create an index that starts with the proposed shard key before sharding the collection",
"code" : 72,
"codeName" : "InvalidOptions",
"operationTime" : Timestamp(1579232071, 4),
"$clusterTime" : {
"clusterTime" : Timestamp(1579232071, 4),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
6、分片管理
6.1、sh.status()查看集群信息
sh.status()可查看分片、数据库和分片集合的信息。块的数量较多时,sh.status()会输出块的状态,而非打印每个块的相关信息。如需查看所有的块,可使用sh.status(true)命令来打印尽可能详细的信息。
mongos> use admin
switched to db admin
mongos> db.runCommand({ enablesharding:"dest" })
{
"ok" : 1,
"operationTime" : Timestamp(1579232062, 3),
"$clusterTime" : {
"clusterTime" : Timestamp(1579232062, 3),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
mongos> db.runCommand({ shardcollection: "dest.city", key: { code:1}})
{
"ok" : 0,
"errmsg" : "Please create an index that starts with the proposed shard key before sharding the collection",
"code" : 72,
"codeName" : "InvalidOptions",
"operationTime" : Timestamp(1579232071, 4),
"$clusterTime" : {
"clusterTime" : Timestamp(1579232071, 4),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
6.2、查询配置信息
分片集群的所有配置信息都保存在配置服务器中,可直接访问config数据库来获取配置信息。
连接上配置服务器集群后,通过如下操作找到配置数据库:
show dbs
admin 0.000GB
config 0.001GB
local 0.000GB
use config
switched to db config
show collections
changelog
chunks
collections
databases
lockpings
locks
migrations
mongos
shards
tags
transactions
version
6.2.1、config.shards集合
config.shards集合中跟踪记录集群内所有的分片信息。其结构如下:
db.shards.findOne()
{
"_id" : "shard",
"host" : "shard/localhost:27117,localhost:27118,localhost:27119",
"state" : 1
}
分片id为副本集名称。
6.2.2、config.databases集合
config.databases集合跟踪记录集群中所有数据库的信息,不论数据库是否分片。
db.databases.findOne()
{
"_id" : "city",
"primary" : "shard",
"partitioned" : true,
"version" : {
"uuid" : UUID("b8a1ef6f-4673-40bd-84d7-10a30918348e"),
"lastMod" : 1
}
}
primary标识数据的主分片,所有新集合均默认被创建在主分片上。
6.2.3、config.collection集合
config.collection集合跟踪记录分片集合的信息,非分片集合信息除外。
db.collections.findOne()
{
"_id" : "config.system.sessions",
"lastmodEpoch" : ObjectId("5e21286a75e4dc2b10df9cf3"),
"lastmod" : ISODate("1970-02-19T17:02:47.296Z"),
"dropped" : false,
"key" : {
"_id" : 1
},
"unique" : false,
"uuid" : UUID("60aa6a51-d8fd-4a29-bbcc-6923b277c97e")
}
_id:集合命名空间;
key:片键;
unique:片键是否唯一,片键默认是不唯一的;
6.2.4、config.chunks集合
config.chunks集合跟踪记录分片集合中所有块信息;
{
"_id": "config.system.sessions-_id_MinKey",
"ns": "config.system.sessions",
"min": {
"_id": {
"$minKey": 1
}
},
"max": {
"_id": {
"$maxKey": 1
}
},
"shard": "shard",
"lastmod": Timestamp(1, 0),
"lastmodEpoch": ObjectId("5e21286a75e4dc2b10df9cf3"),
"history": [{
"validAfter": Timestamp(1579231338, 3),
"shard": "shard"
}]
}
_id:块唯一标识符。该标识符通常由命名空间、片键和块的下边界值组成;
ns:块所属是集合名称;
min:块范围的最小值(包含);
max:块范围的最大值(不包含);
shard:块所属分片;
6.2.5、config.changelog集合
config.changelog集合用于跟踪记录集群的操作,此集合会记录所有的拆分和迁移操作。
db.changelog.findOne()
{
"_id" : "010A1905050081:27217-2020-01-17T11:19:39.023+0800-5e2127cbba5ea4e9b1f8103c",
"server" : "010A1905050081:27217",
"shard" : "config",
"clientAddr" : "127.0.0.1:56969",
"time" : ISODate("2020-01-17T03:19:39.023Z"),
"what" : "addShard",
"ns" : "",
"details" : {
"name" : "shard",
"host" : "shard/localhost:27117"
}
}
6.2.6、config.tags集合
config.tags集合保存系统配置分片的标签,每个标签都与一个块分为相关联。
6.2.7、config.settings集合
config.settings集合含有当前均衡器设置和块大小的文档信息。通过修改该文档,可关闭或开启均衡器,也可修改块大小。