08-分片集群基本操作

分片集群基本操作

一、概念

1.1 数据块

  • 数据块默认大小是64MB,当一个块的数据超过该大小之后,块会裂变为更小的块,块和块直接的数据没有交集。

1.2 平衡器

  • 周期性检查分片之间的块的数量是否均衡,如果差值超过阈值(8),就会进行块的迁移,将块迁移到数量较少的分片。

二、分片查询

2.1 查询集群状态

 sh.status()
 sh.status(true)

2.2检查配置信息

mongos> use config
switched to db config
mongos> show tables;(等价于show collections)
actionlog       //记录平衡器的相关操作日志。
changelog       //跟踪记录集群的操作,包括集合分片操作、块拆分和迁移、添加删除分片等。例如块拆分信息:
chunks          //存储集合分片所有块信息
collections     //记录所有分片集合信息,该记录中的记录不会因为分片集合被删除而被清除。
databases       //记录集群中数据库的信息,不管数据库有没有分片。如数据库开启了分片,那么"partitioned" :字段的值为true。"primary"记录数据库所属的主分片。所有新集合默认创建在数据库主分片上。比如当前的集合在某个分片上面还没有数据那么不会在该分片上创建集合。所以如果某个分片存在分片的集合,那么必须将集合的数据移走或者将集合删除,否则该分片无法删除。
lockpings       //记录分片运行是否正常的ping记录信息
locks           //记录存储分布式锁操作信息。
migrations
mongos          //记录mongos的相关信息,记录每一个mongos实例的信息。
shards          //群集分片信息
tags            //记录分片标签信息
transactions
version         //群集版本信息

2.3 修改配置信息

  • 如果需要修改配置信息,需要通过连接到mongos切换到config数据库操作而不是直接连接到配置服务器中操作

2.4 查看网络连接

db.adminCommand({"connPoolStats":1})

三、分片管理

3.1 添加分片

  • 假如已经有一个分片集群在运行,包含若干分片,现有一个副本集需要假如到该分片集群,副本集的名称是sh1,sh1包含一个192.168.11.67:30001的mongod实例,那么将次副本集加入到集群的操作是:
//访问分片集群的mongos:
./mongo 192.168.11.67:27017/admin   
//连接admin或者切换到admin操作
use admin
db.runCommand( { addshard:"sh1/192.168.11.66:30001",name:"sh1" })
db.runCommand( { addshard:"sh2/192.168.11.67:30001",name:"sh2" })
执行后返回类似信息:
{
	"shardAdded" : "sh3",
	"ok" : 1,
	"operationTime" : Timestamp(1557344124, 505),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1557344124, 505),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}
sh.status();//列出刚刚添加的集群说明是正确的

PS:添加分片也可以使用sh.addShard( "sh1/192.168.11.67:30001" )

3.2 删除分片

  • 先当前分片对应数据库挪到其它的分片上。这里的"products"指的是数据库名(如果需要移除的分片是一个表的Primary,那么无法简单的将分片移除,需要进行数据的迁移,反之可以直接执行删除分片操作)
//访问分片集群的mongos:
./mongo 192.168.11.67:27017/admin
 db.runCommand( { movePrimary: "products", to: "sh1" })
  • 然后再删除分片
db.runCommand({"removeShard":"sh2"});
  • 注意:需要多次执行db.runCommand({“removeShard”:“sh2”});命令来删除分片,首先平衡器会将分片上的数据进行迁移,可以通过sh.isBalancerRunning()命令查询是否迁移完成,迁移完成之后再次执行删除分片命令彻底移除分片。

  • 集合不分片

每个集合都有一个主分片,默认情况下集合是不分片的,对于没有开启分片的集合,数据存储在它的主分片,可以通过命令将数据从主分片迁移到另外的分片。在mongos里面操作,如下是将test集合移到shard0001这个分片。
db.runCommand( { movePrimary : "test", to : "shard0001" } )

变更分片信息之后,mongos里的配置信息变得过时了。MongoDB提供命令:flushRouterConfig 强制mongos从config server获取最新的配置信息,刷新mongos的缓存。
db.adminCommand({"flushRouterConfig":1})

3.3 平衡器管理

3.3.1 开启平衡器
use admin
sh.startBalancer()
或者
sh.setBalancerState(true)
3.3.2 关闭平衡器
use admin
sh.stopBalancer()
或者
sh.setBalancerState(false);
3.3.3 查看平衡器是否开启
  • 查看是否关闭,返回flase标识平衡器已关闭,还需要查询均衡器正在运行情况
sh.getBalancerState() //true表示开始 false表示关闭
3.3.4 查看平衡器是否在运行
sh.isBalancerRunning()  //true表示正在运行、false表示没有运行
3.3.5 指定平衡时间
  • 可以指定平衡时间,避免业务高峰时间平衡过程占用资源。指定平衡时间首先要确保平衡器是开启的,小时数0-23,分钟数0-59
db.settings.update(
    {"_id":"balancer"},
    {"$set":
        {
            "activeWindow":
                {
                    "start":"13:00",
                    "stop":"16:00"
                }
        }
    },
    {upsert:true}
)
3.3.6 关闭平衡时间
db.settings.update({ _id : "balancer" }, { $unset : { activeWindow : true } })
3.3.7 关闭/开启指定集合的平衡器
//关闭:
sh.disableBalancing("test.aa")
//开启:
sh.enableBalancing("test.aa")
3.3.8 备份时注意事项
  • 在执行备份前需要关闭平衡器,但是均衡器的关闭不是立即就完成,所以还需要查询均衡器是否正在运行,不要在平衡器处于活动状态时备份,可以备份操作前执行以下查询:
sh.getBalancerState()
sh.isBalancerRunning()
  • MonogDB的balancer能支持非常灵活的配置策略来适应各种需求,前面给出了针对指定的集合来开启、关闭和支持配置时间窗口,只在指定的时间段内进行迁移。

3.4 块管理

3.4.1 chunk
3.4.1.1 介绍
  • 分片集群中数据根据片键定位到指定的分片之后,然后是按照chunk为单位存储的(阈值默认64MB)。
  • 每一个数据库有一个主分片(primary shard),对于没有分片的集合,或者分片了但是还没有触发Chunk分裂迁移的集合,数据都会保存在主分片。 (对于启用了分片的集合,首先会在primary shard上创建一个片键为
    [minKey,maxKey]的chunk,随着数据的写入再发生chunk的分裂和迁移。)
3.4.1.2 chunk分裂
  • MongoDB的chunk分裂只会在mongos写入数据时触发,当写入的数据超过一定量时,就会触发 chunk 的分裂,具体规则如下:
集合 CHUNK 数量分裂阈值
11024B
[1,3)0.5MB
[3,10)16 MB
[10,20)32 MB
[20,max)64 MB
  • 写入数据会导致chunk变大,当其大小达到阈值之后,就会分裂,分裂之后如果各个shard上的chunck分布不均匀,就会触发chunk迁移(chunk数量大于等于8个则认为不均匀,chunk就会在不同的片之间迁移)。
PS: mongos 上有个 sharding.autoSplit 的配置项,可用于控制是否自动触发 chunk 分裂,默认是开启的。如无专业人士指导,强烈建议不要关闭 autoSplit。
3.4.1.3 chunk迁移
  • 默认情况下MongoDB会开启balancer,在各个shard间迁移chunk来让各个shard间负载均衡。用户也可以手动的调用moveChunk命令在shard之间迁移数据。Balancer 在工作时,会根据shard tag、集合的 chunk 数量、shard 间 chunk 数量差值 来决定是否需要迁移。
3.4.1.4 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 大小会随着写入不断增长,直到达到目标大小。
  • 可以预分片提前分裂减小分裂及迁移的影响,但是只支持hash分片
3.4.2 查看块大小
  • chunksize默认的大小是64M,用mongos连接到config数据库,通过查看config.settings可以看到这个值:
mongos> use config
mongos> db.settings.find()
{ "_id" : "chunksize", "value" : 64 }
3.4.3 修改块大小
mongos> use config;
查询当前块大小
mongos> db.settings.find({"_id":"chunksize"})
修改块大小
//db.settings.save( { _id:"chunksize", value: <sizeInMB> } )
mongos> db.settings.save( { _id:"chunksize", value: 64 } );
3.4.4 查询文档块信息
mongos> use config
db.getCollection('chunks').find({})
db.getCollection('chunks').find({"ns":"test.xxxx"}) //ns是namespace,其实就是dbName.collectinName,查询指定表的块信息
查询信息示例:
{ 
    "_id" : "ifaas_data.multobj-targetType_"face"time_new Date(1548104815000)", 
    "lastmod" : Timestamp(39, 37), 
    "lastmodEpoch" : ObjectId("5cdbb852fd1676a4c83af809"), 
    "ns" : "ifaas_data.multobj", 
    "min" : { "targetType" : "face", "time" : ISODate("2019-01-21T21:06:55Z") }, 
    "max" : { "targetType" : "face", "time" : ISODate("2019-01-23T11:51:01Z") }, 
    "shard" : "sh2" 
}
3.4.5 移动文档块信息
  • 移动块只需要指定块的返回内的随便一个值即可,注意块的范围不包含上限。
sh.moveChunk("test.xxxx",{"username":"$minKey"},"sh1")
 //注意这里的username是一个片键,$minKey是片键值的下限,sh1是期望移动到的目标分片,
//在查询文档块信息的时候,可以看到根据片键的从小到大的范围将所有记录分割为块,这里相当
//于通过下限值标识了一个需要移动的块
3.4.6 拆分块
  • 如果块的大小超过setting设置的最大块大小时,系统会禁止移动块,这时候需要将块进行拆分。这里需要指定新的块范围,指定下限即可。
sh.splitAt("test.xxxx",{ "username" :"p" }) 
//这里和上面移动文档块信息很类似,username是片键,指定下限即可将指定的块拆分
3.4.7 查看指定块大小
  • 下面查找test.xxx集合的指定块的大小,通过片键和片键的上下限来指定块,单位字节,需要指定块的范围。
db.runCommand({ dataSize: "test.xxxx", keyPattern: { "username": 1 }, min: { "username" : "b" }, max: { "username" : "c" } })
3.4.8 特大块
  • 如果使用year/month/day字段作为分片,某一天业务遭受攻击导致这天的数据量暴增,但是由于分片的值已经的最小单位了无法再拆分了,这个时候通过块拆分已
    经无法解决问题,可以手动将块移动到非热点的分片上。

3.5 刷新配置信息

  • mongos有时无法从配置服务器正确更新配置信息,可以使用flushRouterConfig命令手动刷新缓存,如果刷新还无法解决需要重启mongos进程。
db.adminCommand({"flushRouterConfig":1})

3.6 删除分片数据库

use news
db.dropDatabase() //删除指定的数据库

四、副本集操作

4.1 副本优先级

  • 可以设置副本集中某个节点成为Primary的优先级,按照权重设置。如果我们在分片集群中或者一个单纯的副本集中,我们期望某一个节点成
    为Primary的优先级更大(比如机器配置好),怎么做,下面是教程。
  • 首先连接目前的Primary
mongo --host ip --port port //连接目前的副本集Primary主节点
cfg = rs.conf() //执行命令查看配置,返回信息中我们可以看到节点信息,仲裁的priority是0
cfg.members[0].priority=50 //将我们期望的主节点的priority设置更好,范围是1-100,越大优先级越高,然后rs.reconfig(cfg)刷新配置,这里的0是前面信息里面的id
rs.reconfig(cfg) //刷新配置
cfg = rs.conf() //执行cfg = rs.conf()查询配置,我们看到priority已经生效

4.2 详细过程

4.2.1 首先连接目前的Primary
mongo --host ip --port port //连接目前的副本集Primary主节点
执行:
4.2.2 查看配置
  • 执行: cfg = rs.conf(),下面是返回信息,我们可以看到有3个节点,一主一从,一个仲裁,但是主从的priority都是1,仲裁的priority是0
{
	"_id" : "sh3",
	"version" : 1,
	"protocolVersion" : NumberLong(1),
	"members" : [
		{
			"_id" : 0,
			"host" : "192.168.12.204:30001",
			"arbiterOnly" : false,
			"buildIndexes" : true,
			"hidden" : false,
			"priority" : 1,
			"tags" : {
				
			},
			"slaveDelay" : NumberLong(0),
			"votes" : 1
		},
		{
			"_id" : 1,
			"host" : "192.168.12.212:30005",
			"arbiterOnly" : false,
			"buildIndexes" : true,
			"hidden" : false,
			"priority" : 1,
			"tags" : {
				
			},
			"slaveDelay" : NumberLong(0),
			"votes" : 1
		},
		{
			"_id" : 2,
			"host" : "192.168.12.204:30003",
			"arbiterOnly" : true,
			"buildIndexes" : true,
			"hidden" : false,
			"priority" : 0,
			"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("5cd23b82570019b2db661b69")
	}
}

4.2.3 修改配置
  • 将我们期望的主节点的priority设置更好,范围是1-100,越大优先级越高,然后rs.reconfig(cfg)刷新配置
sh3:PRIMARY> cfg.members[0].priority=50
50
sh3:PRIMARY> rs.reconfig(cfg)
{ "ok" : 1 }

4.2.4 查询配置
  • 执行cfg = rs.conf()查询配置,我们看到priority已经生效了
{
			"_id" : 0,
			"host" : "192.168.12.204:30001",
			"arbiterOnly" : false,
			"buildIndexes" : true,
			"hidden" : false,
			"priority" : 50,
			"tags" : {
				
			},
			"slaveDelay" : NumberLong(0),
			"votes" : 1
		}
  • 我在一个副本集验证,进入Primary之后,将Secondary的优先级设置高之后,所在的Primary很快就切换为Secondary了,原本的Secondary成为了主节点。我们在多台机器部署集群的时候,可以很好的通过
    这个配置来让Primary运行在我们期望的设备,因为Primary默认是需要承担全部的读写请求的。

五、数据库启用分片

  • 数据库下的集合启用分配,指定片键
sh.shardCollection("dbName.collName",{"username":1});//单键片键
sh.shardCollection("test.bbbb",{"username":1,"time":1});//组合片键

六、参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值