当前位置:Gxlcms > 数据库问题 > MongoDB 3 分片集群安装配置

MongoDB 3 分片集群安装配置

时间:2021-07-01 10:21:17 帮助过:5人阅读

# mongod.conf

# for documentation of all options, see:
#   http://docs.mongodb.org/manual/reference/configuration-options/

# where to write logging data.
systemLog:
  destination: file
  logAppend: true
  path: /var/log/mongodb/mongod.log

# Where and how to store data.
storage:
  dbPath: /var/lib/mongo
  journal:
    enabled: true
#  engine:
#  mmapv1:
#  wiredTiger:

# how the process runs
processManagement:
  fork: true  # fork and run in background
  pidFilePath: /var/run/mongodb/mongod.pid  # location of pidfile

# network interfaces
net:
  port: 27019
  bindIp: 0.0.0.0  # Listen to local interface only, comment to listen on all interfaces.


#security:

#operationProfiling:

replication:
  replSetName: cfgReplSet

sharding:
  clusterRole: configsvr

## Enterprise-Only Options

#auditLog:

#snmp:
  • 启动三台config server 的mongod 服务

    [root@test4 ~]# service mongod start
    Starting mongod:                                           [  OK  ]
    
    [root@test5 ~]# service mongod start
    Starting mongod:                                           [  OK  ]
    
    [root@test6 ~]# service mongod start
    Starting mongod:                                           [  OK  ]

    同样,config server 的副本集配置如上文所示,这里的代码就省略了

  • 配置启动 mongos 路由主机

    [root@test7 ~]# mongos --configdb cfgReplSet/test4.lan,test5.lan,test6.lan:27019 --logpath /var/log/mongodb/mongos.log --fork --port 30000
    about to fork child process, waiting until server is ready for connections.
    forked process: 3338
    child process started successfully, parent exiting

    MongoDB 版本 >3.2 启动mongos 的时候,需要跟上 config server 的副本集名称 (这里是 cfgReplSet

  • 连接 mongos 测试

    [root@test7 ~]# mongo test7.lan:30000
    MongoDB shell version v3.4.4
    connecting to: test7.lan:30000
    MongoDB server version: 3.4.4
    Server has startup warnings: 
    2017-04-24T23:30:47.285+0800 I CONTROL  [main] 
    2017-04-24T23:30:47.285+0800 I CONTROL  [main] ** WARNING: Access control is not enabled for the database.
    2017-04-24T23:30:47.285+0800 I CONTROL  [main] **          Read and write access to data and configuration is unrestricted.
    2017-04-24T23:30:47.285+0800 I CONTROL  [main] ** WARNING: You are running this process as the root user, which is not recommended.
    2017-04-24T23:30:47.285+0800 I CONTROL  [main] 
    mongos> show dbs
    admin   0.000GB
    config  0.000GB
    mongos> use config
    switched to db config
    mongos> show collections
    chunks
    lockpings
    locks
    migrations
    mongos
    shards
    tags
    version
    mongos> db.shards.find()
    # 这里没有返回文档,也说明分片集群中并没有添加可用分片集群。
  • 配置分片集群:shard

    mongos> sh.addShard("shard-a/test1.lan,test2.lan,test3.lan")
    { "shardAdded" : "shard-a", "ok" : 1 }
    
    mongos> db.shards.find()
    { "_id" : "shard-a", "host" : "shard-a/test1.lan:27017,test2.lan:27017,test3.lan:27017", "state" : 1 }
    
    mongos> sh.addShard("shard-b/test1.lan:37017,test2.lan:37017,test3.lan:37017")
    { "shardAdded" : "shard-b", "ok" : 1 }
    
    mongos> db.shards.find()
    { "_id" : "shard-a", "host" : "shard-a/test1.lan:27017,test2.lan:27017,test3.lan:27017", "state" : 1 }
    { "_id" : "shard-b", "host" : "shard-b/test1.lan:37017,test2.lan:37017,test3.lan:37017", "state" : 1 }
    # 检查分片集群的分片副本集数量,方法一
    
    mongos> db.getSiblingDB(‘config‘).shards.find()
    { "_id" : "shard-a", "host" : "shard-a/test1.lan:27017,test2.lan:27017,test3.lan:27017", "state" : 1 }
    { "_id" : "shard-b", "host" : "shard-b/test1.lan:37017,test2.lan:37017,test3.lan:37017", "state" : 1 }
    # 检查分片集群的分片副本集数量,方法二
    
    mongos> use admin
    switched to db admin
    mongos> db.runCommand({listshards: 1})
    {
    	"shards" : [
    		{
    			"_id" : "shard-a",
    			"host" : "shard-a/test1.lan:27017,test2.lan:27017,test3.lan:27017",
    			"state" : 1
    		},
    		{
    			"_id" : "shard-b",
    			"host" : "shard-b/test1.lan:37017,test2.lan:37017,test3.lan:37017",
    			"state" : 1
    		}
    	],
    	"ok" : 1
    }
    # 检查分片集群的分片副本集数量,方法三
  • 配置分片集合:接下来的步骤就是在数据库上启动分片。分片不会自动完成,而是需要在数据库里提前为集合做好设置才行。

    mongos> sh.enableSharding("test2_db")        # 该库可以是已存在的,也可以是暂不存在的
    { "ok" : 1 }
    
    mongos> db.getSiblingDB("config").databases.find()
    { "_id" : "test2_db", "primary" : "shard-a", "partitioned" : true }
    # sharding 分片库的配置库 databases 集合已经有相应的配置记录了。
    
    mongos> sh.status()
    --- Sharding Status --- 
      sharding version: {
    	"_id" : 1,
    	"minCompatibleVersion" : 5,
    	"currentVersion" : 6,
    	"clusterId" : ObjectId("58fe17e90b3df66581ff6b09")
    }
      shards:
    	{  "_id" : "shard-a",  "host" : "shard-a/test1.lan:27017,test2.lan:27017,test3.lan:27017",  "state" : 1 }
    	{  "_id" : "shard-b",  "host" : "shard-b/test1.lan:37017,test2.lan:37017,test3.lan:37017",  "state" : 1 }
      active mongoses:
    	"3.4.4" : 1
     autosplit:
    	Currently enabled: yes
      balancer:
    	Currently enabled:  yes
    	Currently running:  no
    		Balancer lock taken at Mon Apr 24 2017 23:21:13 GMT+0800 (CST) by ConfigServer:Balancer
    	Failed balancer rounds in last 5 attempts:  0
    	Migration Results for the last 24 hours: 
    		No recent migrations
      databases:
    	{  "_id" : "test2_db",  "primary" : "shard-a",  "partitioned" : true }
    # 分片状态中更能方便的查看当前分片的状态信息,包括分片集群成员 以及 分片数据库,分片机制等。
    
    mongos> sh.shardCollection("test2_db.users", {username: 1, _id: 1})        
    { "collectionsharded" : "test2_db.users", "ok" : 1 }
    # 此处,我们选择 username _id 作为组合分片键,组合分片键必须是一个索引
    # 如果集合为空,那么该行命令会自动在集合中创建该索引,如果集合已存在对应数据,且该组合键的索引没有事先创建好,那么这条语句就会抛出错误
    # 需要手动到集合创建该组合的索引,之后才能作为分片键
    
    mongos> db.getSiblingDB("config").collections.find().pretty()
    {
    	"_id" : "test2_db.users",
    	"lastmodEpoch" : ObjectId("58fe21de224dc86230e9a8f7"),
    	"lastmod" : ISODate("1970-02-19T17:02:47.296Z"),
    	"dropped" : false,
    	"key" : {
    		"username" : 1,
    		"_id" : 1
    	},
    	"unique" : false
    }
    # 配置完成后,config.collections 就存在了相应集合的分片键信息。

  • 来看看分片集合在单独分片副本集中的存在形式

    首先需要找到该库已经被分配到了哪个分片之上(由于该库之前并没有数据,所以创建分片键的时候,会自动插入索引数据,自动按照默认配置路由到其中一个分片键集群之中)

    mongos> sh.status()
    --- Sharding Status --- 
      sharding version: {
    	"_id" : 1,
    	"minCompatibleVersion" : 5,
    	"currentVersion" : 6,
    	"clusterId" : ObjectId("58fe17e90b3df66581ff6b09")
    }
      shards:
    	{  "_id" : "shard-a",  "host" : "shard-a/test1.lan:27017,test2.lan:27017,test3.lan:27017",  "state" : 1 }
    	{  "_id" : "shard-b",  "host" : "shard-b/test1.lan:37017,test2.lan:37017,test3.lan:37017",  "state" : 1 }
      active mongoses:
    	"3.4.4" : 1
     autosplit:
    	Currently enabled: yes
      balancer:
    	Currently enabled:  yes
    	Currently running:  no
    		Balancer lock taken at Mon Apr 24 2017 23:21:13 GMT+0800 (CST) by ConfigServer:Balancer
    	Failed balancer rounds in last 5 attempts:  0
    	Migration Results for the last 24 hours: 
    		No recent migrations
      databases:
    	{  "_id" : "test2_db",  "primary" : "shard-a",  "partitioned" : true }
    		test2_db.users
    			shard key: { "username" : 1, "_id" : 1 }
    			unique: false
    			balancing: true
    			chunks:
    				shard-a	1
    			{ "username" : { "$minKey" : 1 }, "_id" : { "$minKey" : 1 } } -->> { "username" : { "$maxKey" : 1 }, "_id" : { "$maxKey" : 1 } } on : shard-a Timestamp(1, 0) 
    # 最后这行 databases 看到了,该库的该数据块(chunks) 被分配到了 shard-a 副本集中,那么我们接下来就可以直接到 shard-a 中查看该库中users集合的文档信息。
    
    # 登录到 shard-a 副本集中进行查看
    shard-a:PRIMARY> show dbs
    admin     0.000GB
    local     0.000GB
    test2_db  0.000GB
    shard-a:PRIMARY> use test2_db
    switched to db test2_db
    shard-a:PRIMARY> db.users.find()    # 该集合暂时没有文档
    
    shard-a:PRIMARY> db.users.getIndexes()        # 查看该集合的索引配置信息
    [
    	{
    		"v" : 2,
    		"key" : {
    			"_id" : 1
    		},
    		"name" : "_id_",
    		"ns" : "test2_db.users"
    	},
    	{
    		"v" : 2,
    		"key" : {
    			"username" : 1,
    			"_id" : 1
    		},
    		"name" : "username_1__id_1",
    		"ns" : "test2_db.users"
    	}    # 查看到了两个索引,第一个索引 _id 为系统默认添加的索引,第二个索引就是创建分片键的时候自动创建的组合键索引
    ]


    写入数据到分片集群

    # 首先创建一个数据对象,用来填充文档大小
    mongos> data = new Array(2049).join("abcd ")
    mongos> data.length
    10240
    # data 大小为 1MB
    
    mongos> for (var i=0; i < 100; i++){
    ...         db.getSiblingDB("test2_db").users.insert({
    ...             username: "Join" + i,
    ...             age: i % 13 + 20,
    ...             data: data }
    ...         )
    ... }
    WriteResult({ "nInserted" : 1 })
    # 批量插入 100 条文档,每个文档约为 1MB 大小。
    
    # 接下来看看有了这么多文档过后,会怎么分片。
    mongos> db.getSiblingDB("config").chunks.count()
    3
    # 插入这么多数据以后,就会发现多了几个数据块。我们可以通过检查集合中的数据库的数量来验证这个猜想
    
    mongos> db.getSiblingDB("config").chunks.find().pretty()
    {
    	"_id" : "test2_db.users-username_MinKey_id_MinKey",
    	"lastmod" : Timestamp(2, 1),
    	"lastmodEpoch" : ObjectId("58fe21de224dc86230e9a8f7"),
    	"ns" : "test2_db.users",
    	"min" : {
    		"username" : { "$minKey" : 1 },
    		"_id" : { "$minKey" : 1 }
    	},
    	"max" : {
    		"username" : "Join1",
    		"_id" : ObjectId("58fe293756525c8a54e2a5af")
    	},
    	"shard" : "shard-a"
    }
    {
    	"_id" : "test2_db.users-username_\"Join1\"_id_ObjectId(‘58fe293756525c8a54e2a5af‘)",
    	"lastmod" : Timestamp(1, 2),
    	"lastmodEpoch" : ObjectId("58fe21de224dc86230e9a8f7"),
    	"ns" : "test2_db.users",
    	"min" : {
    		"username" : "Join1",
    		"_id" : ObjectId("58fe293756525c8a54e2a5af")
    	},
    	"max" : {
    		"username" : "Join2",
    		"_id" : ObjectId("58fe293756525c8a54e2a5b0")
    	},
    	"shard" : "shard-a"
    }
    {
    	"_id" : "test2_db.users-username_\"Join2\"_id_ObjectId(‘58fe293756525c8a54e2a5b0‘)",
    	"lastmod" : Timestamp(2, 0),
    	"lastmodEpoch" : ObjectId("58fe21de224dc86230e9a8f7"),
    	"ns" : "test2_db.users",
    	"min" : {
    		"username" : "Join2",
    		"_id" : ObjectId("58fe293756525c8a54e2a5b0")
    	},
    	"max" : {
    		"username" : { "$maxKey" : 1 },
    		"_id" : { "$maxKey" : 1 }
    	},
    	"shard" : "shard-b"
    }
    # 查看每个数据块的详细分片信息,发现有两个块被存储在 shard-a 副本集中,还有一个数据块被存储在 shard-b 副本集中
    
    # 我们也可以通过 sh.status() 来更直观的看到相关信息。
    mongos> sh.status()
    --- Sharding Status --- 
      sharding version: {
    	"_id" : 1,
    	"minCompatibleVersion" : 5,
    	"currentVersion" : 6,
    	"clusterId" : ObjectId("58fe17e90b3df66581ff6b09")
    }
      shards:
    	{  "_id" : "shard-a",  "host" : "shard-a/test1.lan:27017,test2.lan:27017,test3.lan:27017",  "state" : 1 }
    	{  "_id" : "shard-b",  "host" : "shard-b/test1.lan:37017,test2.lan:37017,test3.lan:37017",  "state" : 1 }
      active mongoses:
    	"3.4.4" : 1
     autosplit:
    	Currently enabled: yes
      balancer:
    	Currently enabled:  yes
    	Currently running:  no
    		Balancer lock taken at Mon Apr 24 2017 23:21:13 GMT+0800 (CST) by ConfigServer:Balancer
    	Failed balancer rounds in last 5 attempts:  0
    	Migration Results for the last 24 hours: 
    		1 : Success
      databases:
    	{  "_id" : "test2_db",  "primary" : "shard-a",  "partitioned" : true }
    		test2_db.users
    			shard key: { "username" : 1, "_id" : 1 }
    			unique: false
    			balancing: true
    			chunks:
    				shard-a	2
    				shard-b	1
    			{ "username" : { "$minKey" : 1 }, "_id" : { "$minKey" : 1 } } -->> { "username" : "Join1", "_id" : ObjectId("58fe293756525c8a54e2a5af") } on : shard-a Timestamp(2, 1) 
    			{ "username" : "Join1", "_id" : ObjectId("58fe293756525c8a54e2a5af") } -->> { "username" : "Join2", "_id" : ObjectId("58fe293756525c8a54e2a5b0") } on : shard-a Timestamp(1, 2) 
    			{ "username" : "Join2", "_id" : ObjectId("58fe293756525c8a54e2a5b0") } -->> { "username" : { "$maxKey" : 1 }, "_id" : { "$maxKey" : 1 } } on : shard-b Timestamp(2, 0) 
    # 这个方法会打印所有的数据库信息,并且包含范围信息。


    表象背后,MongoDB 底层依赖 2 个机制来保持集群的平衡:分割与迁移。


    分割是把一个大的数据库分割为 2 个更小的数据块的过程。它只会在数据块大小超过最大限制的时候才会发生,目前的默认设置是 64MB。分割是必须的,因为数据块太大就难以在整个集合中分布。


    迁移就是在分片之间移动数据块的过程。当某些分片服务器包含的数据块数量大大超过其他分片服务器就会触发迁移过程,这个触发器叫做迁移回合(migration round)。在一个迁移回合中,数据块从某些分片服务器迁移到其他分片服务器,直到集群看起来相对平衡为止。我们可以想象一下这两个操作,迁移比分割昂贵得多。


    实际上,这些操作不应该影响我们,但是明白这一点非常有用,当遇到性能问题的时候就要想到可能它们正在迁移数据。如果插入的数据分布均匀,各个分片上的数据集应该差不多以相同的速度增长,则迁移应该不会频繁发生。

    本文出自 “Professor哥” 博客,请务必保留此出处http://professor.blog.51cto.com/996189/1919016

    MongoDB 3 分片集群安装配置

    标签:mongodb 副本集 分片 分片集合 分片键 高可用 读写分离 负载均衡 ha

    人气教程排行