将副本集转换为分片群集

在本页面

Overview

本教程将单个三成员副本集转换为具有两个分片的分片集群。每个分片都是一个独立的三元副本集。本教程特定于 MongoDB 3.6. 对于其他版本的 MongoDB,请参阅相应版本的《 MongoDB 手册》。

步骤如下:

Prerequisites

本教程总共使用十台服务器:一台服务器用于mongos,三台服务器分别用于第replica set,第二个副本集和配置服务器副本集

每个服务器在系统内必须具有可解析的域,主机名或 IP 地址。

本教程使用默认数据目录(例如/data/db/data/configdb)。创建具有适当权限的适当目录。要使用其他路径,请参见配置文件选项

Procedures

设置初始副本集

此过程将创建初始的三成员副本集rs0。副本集成员位于以下主机上:mongodb0.example.netmongodb1.example.netmongodb2.example.net

使用适当的选项启动副本集的每个成员。

对于每个成员,使用以下设置启动mongod实例:

如果您的应用程序连接到多个副本集,则每个副本集应具有不同的名称。某些驱动程序通过副本集名称对副本集连接进行分组。

  • net.bindIp选项设置为 IP 或以逗号分隔的 IP 列表,然后

  • 根据您的部署设置任何其他设置。

在本教程中,三个mongod实例与以下主机关联:

副本集成员Hostname
Member 0mongodb0.example.net
Member 1mongodb1.example.net
Member 2mongodb2.example.net

以下示例通过--replSet--bind_ip命令行选项指定副本集名称和 ip 绑定:

Warning

绑定到非 localhost(例如可公开访问)的 IP 地址之前,请确保已保护群集免受未经授权的访问。有关安全建议的完整列表,请参见Security Checklist。至少考虑enabling authentication加强网络基础设施

mongod --replSet "rs0" --bind_ip localhost,<ip address of the mongod host>

对于<ip address>,请指定mongod实例的 IP 地址或主机名,远程 Client 端(包括副本集的其他成员)可以使用该 IP 地址或主机名连接到该实例。

另外,您也可以在configuration file中指定副本集名称ip addresses

replication:
   replSetName: "rs0"
net:
   bindIp: localhost,<ip address>

要以配置文件开始mongod,请使用--config选项指定配置文件的路径:

mongod --config <path-to-config>

在生产部署中,您可以配置init script来 Management 此过程。初始化脚本超出了本文档的范围。

将 mongo shell 连接到其中一个 mongod 实例。

从运行mongod的同一台计算机(在本教程中为mongodb0.example.net)中,启动mongo Shell。要连接mongod并在27017的默认端口上监听 localhost,只需发出:

mongo

根据您的路径,您可能需要指定mongo二进制文件的路径。

启动副本集。

mongo shell 中,对副本集成员 0 运行rs.initiate()

Important

在副本集的仅一个且仅一个 mongod实例上运行rs.initiate()

rs.initiate( {
   _id : "rs0",
   members: [
      { _id: 0, host: "mongodb0.example.net:27017" },
      { _id: 1, host: "mongodb1.example.net:27017" },
      { _id: 2, host: "mongodb2.example.net:27017" }
   ]
})

MongoDB 使用默认副本集配置启动副本集。

创建并填充新集合。

下一步将一百万个文档添加到集合test_collection中,并且可能需要几分钟的时间,具体取决于您的系统。

要确定主要对象,请使用rs.status()

在副本集的主数据库上发出以下操作:

use test
var bulk = db.test_collection.initializeUnorderedBulkOp();
people = ["Marc", "Bill", "George", "Eliot", "Matt", "Trey", "Tracy", "Greg", "Steve", "Kristina", "Katie", "Jeff"];
for(var i=0; i<1000000; i++){
   user_id = i;
   name = people[Math.floor(Math.random()*people.length)];
   number = Math.floor(Math.random()*10001);
   bulk.insert( { "user_id":user_id, "name":name, "number":number });
}
bulk.execute();

有关部署副本集的更多信息,请参见部署副本集

重新启动副本集为分片

在版本 3.4 中进行了更改:对于 MongoDB 3.4 分片群集,必须通过配置文件设置sharding.clusterRole或通过命令行选项--shardsvr,将**的分片mongod实例显式指定为shardsvr

Note

具有shardsvr角色的mongod个实例的默认端口是27018。要使用其他端口,请指定net.port设置或--port选项。

确定主要和次要成员。

mongo shell 连接到其中一个成员,然后运行rs.status()确定主要成员和次要成员。

使用--shardsvr 选项重新启动辅助成员。

一次备份一个,使用--shardsvr选项重新启动每个secondary。要 continue 使用同一端口,请包含--port选项。根据您的部署,包括其他选项,例如--bind_ip

Warning

绑定到非 localhost(例如可公开访问)的 IP 地址之前,请确保已保护群集免受未经授权的访问。有关安全建议的完整列表,请参见Security Checklist。至少考虑enabling authentication加强网络基础设施

mongod --replSet "rs0" --shardsvr --port 27017 --bind_ip localhost,<ip address of the mongod host>

包括适用于您的部署的任何其他选项。对其他辅助服务器重复此步骤。

降级初级。

mongo shell 连接到主节点,然后降级主节点。

rs.stepDown()

使用--shardsvr 选项重新启动主数据库。

使用--shardsvr选项重新启动主数据库。要 continue 使用同一端口,请包含--port选项。

mongod --replSet "rs0" --shardsvr --port 27017 --bind_ip localhost,<ip address of the mongod host>

包括适用于您的部署的任何其他选项。

部署配置服务器副本集和 mongos

此过程为config serversmongos部署三人副本集。

  • 配置服务器使用以下主机:mongodb7.example.netmongodb8.example.netmongodb9.example.net

  • mongos使用mongodb6.example.net

将配置服务器部署为三成员副本集。

mongodb7.example.netmongodb8.example.netmongodb9.example.net上启动配置服务器。指定相同的副本集名称。配置服务器使用默认数据目录/data/configdb和默认端口27019

Warning

绑定到非 localhost(例如可公开访问)的 IP 地址之前,请确保已保护群集免受未经授权的访问。有关安全建议的完整列表,请参见Security Checklist。至少考虑enabling authentication加强网络基础设施

mongod --configsvr --replSet configReplSet --bind_ip localhost,<ip address of the mongod host>

要修改默认设置或包括特定于您的部署的其他选项,请参阅mongod配置文件选项

mongo shell 连接到其中一台配置服务器,然后运行rs.initiate()以启动副本集。

Important

在副本集的仅一个且仅一个 mongod实例上运行rs.initiate()

rs.initiate( {
   _id: "configReplSet",
   configsvr: true,
   members: [
      { _id: 0, host: "mongodb07.example.net:27019" },
      { _id: 1, host: "mongodb08.example.net:27019" },
      { _id: 2, host: "mongodb09.example.net:27019" }
   ]
} )

启动 mongos 实例。

mongodb6.example.net上,启动mongos,指定配置服务器副本集名称,后跟斜杠/以及配置服务器主机名和端口中的至少一个。

mongos --configdb configReplSet/mongodb07.example.net:27019,mongodb08.example.net:27019,mongodb09.example.net:27019  --bind_ip localhost,<ip address of the mongos host>

将初始副本集添加为分片

以下过程将初始副本集rs0添加为分片。

将 mongoShell 连接到 mongos。

mongo mongodb6.example.net:27017/admin

添加分片。

使用sh.addShard方法将分片添加到集群中:

sh.addShard( "rs0/mongodb0.example.net:27017,mongodb1.example.net:27017,mongodb2.example.net:27017" )

添加第二个碎片

以下过程为第二个分片部署了一个新的副本集rs1,并将其添加到集群中。副本集成员位于以下主机上:mongodb3.example.netmongodb4.example.netmongodb5.example.net

在版本 3.4 中进行了更改:对于 MongoDB 3.4 分片群集,必须通过配置文件设置sharding.clusterRole或通过命令行选项--shardsvr,将**的分片mongod实例显式指定为shardsvr

Note

具有shardsvr角色的mongod个实例的默认端口是27018。要使用其他端口,请指定net.port设置或--port选项。

使用适当的选项启动副本集的每个成员。

对于每个成员,启动mongod,通过replSet选项指定副本集名称,并通过--shardsvr选项将其用作分片。根据需要指定其他选项,例如--bind_ip

Warning

绑定到非 localhost(例如可公开访问)的 IP 地址之前,请确保已保护群集免受未经授权的访问。有关安全建议的完整列表,请参见Security Checklist。至少考虑enabling authentication加强网络基础设施

有关特定于复制的参数,请参见Replication Options

mongod --replSet "rs1" --shardsvr --port 27017 --bind_ip localhost,<ip address of the mongod host>

rs1副本集的其他两个成员重复此步骤。

将 mongo shell 连接到副本集成员。

mongo shell 连接到副本集的一个成员(例如mongodb3.example.net)

mongo mongodb3.example.net

启动副本集。

mongo shell 中,运行rs.initiate()以启动一个包含当前成员的副本集。

Important

在副本集的仅一个且仅一个 mongod实例上运行rs.initiate()

rs.initiate( {
   _id : "rs1",
   members: [
       { _id: 0, host: "mongodb3.example.net:27017" },
       { _id: 1, host: "mongodb4.example.net:27017" },
       { _id: 2, host: "mongodb5.example.net:27017" }
   ]
})

将 mongoShell 连接到 mongos。

mongo mongodb6.example.net:27017/admin

添加分片。

在连接到mongosmongo shell 中,使用sh.addShard()方法将分片添加到集群中:

sh.addShard( "rs1/mongodb3.example.net:27017,mongodb4.example.net:27017,mongodb5.example.net:27017" )

分片集合

将 mongoShell 连接到 mongos。

mongo mongodb6.example.net:27017/admin

启用数据库分片。

在分片集合之前,必须首先为集合的数据库启用分片。对数据库启用分片不会重新分配数据,但可以在该数据库中分片集合。

以下操作启用对test数据库的分片:

sh.enableSharding( "test" )

该操作返回操作状态:

{ "ok" : 1 }

确定分片键。

为了使集合成为碎片,请确定碎片密钥。 shard key确定 MongoDB 如何在分片之间分发文档。好的分片键:

  • 具有在所有文档中平均分配的值,

  • 将经常同时访问的文档分组为连续的块,并且

  • 允许在碎片之间有效分配活动。

使用指定的分片键对集合进行分片后,您将无法更改分片键。有关分片键的更多信息,请参见Shard Keys

此过程将使用number字段作为test_collection的分片键。

在分片键上创建索引。

在分片非空集合之前,请创建一个分片索引

use test
db.test_collection.createIndex( { number : 1 } )

分片集合。

test数据库中,对test_collection进行分片,将number指定为分片键。

use test
sh.shardCollection( "test.test_collection", { "number" : 1 } )

该方法返回操作状态:

{ "collectionsharded" : "test.test_collection", "ok" : 1 }

balancer在下次运行时会重新分发大块文档。当 Client 将其他文档插入此集合时,mongos将文档路由到适当的分片。

确认分片处于平衡状态。

要确认平衡活动,请在test数据库中运行db.stats()db.printShardingStatus()

use test
db.stats()
db.printShardingStatus()

db.stats()的示例输出:

{
  "raw" : {
      "rs0/mongodb0.example.net:27017,mongodb1.example.net:27017,mongodb2.example.net:27017" : {
         "db" : "test",
         "collections" : 1,
         "views" : 0,
         "objects" : 640545,
         "avgObjSize" : 70.83200339949052,
         "dataSize" : 45370913,
         "storageSize" : 50438144,
         "numExtents" : 0,
         "indexes" : 2,
         "indexSize" : 24502272,
         "ok" : 1,
         "$gleStats" : {
                     "lastOpTime" : Timestamp(0, 0),
                     "electionId" : ObjectId("7fffffff0000000000000003")
                  }
      },
      "rs1/mongodb3.example.net:27017,mongodb4.example.net:27017,mongodb5.example.net:27017" : {
         "db" : "test",
         "collections" : 1,
         "views" : 0,
         "objects" : 359455,
         "avgObjSize" : 70.83259935179647,
         "dataSize" : 25461132,
         "storageSize" : 8630272,
         "numExtents" : 0,
         "indexes" : 2,
         "indexSize" : 8151040,
         "ok" : 1,
         "$gleStats" : {
            "lastOpTime" : Timestamp(0, 0),
            "electionId" : ObjectId("7fffffff0000000000000001")
         }

      }
  },
  "objects" : 1000000,
  "avgObjSize" : 70,
  "dataSize" : 70832045,
  "storageSize" : 59068416,
  "numExtents" : 0,
  "indexes" : 4,
  "indexSize" : 32653312,
  "fileSize" : 0,
  "extentFreeList" : {
      "num" : 0,
      "totalSize" : 0
  },
  "ok" : 1
}

db.printShardingStatus()的示例输出:

--- Sharding Status ---
sharding version: {
   "_id" : 1,
   "minCompatibleVersion" : 5,
   "currentVersion" : 6,
   "clusterId" : ObjectId("5be0a488039b1964a7208c60")
}
shards:
   {  "_id" : "rs0",  "host" : "rs0/mongodb0.example.net:27017,mongodb1.example.net:27017,mongodb2.example.net:27017",  "state" : 1 }
   {  "_id" : "rs1",  "host" : "rs1/mongodb3.example.net:27017,mongodb4.example.net:27017,mongodb5.example.net:27017",  "state" : 1 }
active mongoses:
   "3.6.8" : 1
autosplit:
   Currently enabled: yes
balancer:
   Currently enabled:  yes
   Currently running:  yes
   Collections with active migrations:
      test.test_collection started at Mon Nov 05 2018 15:16:45 GMT-0500
Failed balancer rounds in last 5 attempts:  0
Migration Results for the last 24 hours:
   1 : Success
databases:
   {  "_id" : "test", "primary" : "rs0", "partitioned" : true }
      test.test_collection
            shard key: { "number" : 1 }
            unique: false
            balancing: true
            chunks:
               rs0   5
               rs1   1
            { "number" : { "$minKey" : 1 } } -->> { "number" : 1195 } on : rs1 Timestamp(2, 0)
            { "number" : 1195 } -->> { "number" : 2394 } on : rs0 Timestamp(2, 1)
            { "number" : 2394 } -->> { "number" : 3596 } on : rs0 Timestamp(1, 5)
            { "number" : 3596 } -->> { "number" : 4797 } on : rs0 Timestamp(1, 6)
            { "number" : 4797 } -->> { "number" : 9588 } on : rs0 Timestamp(1, 1)
            { "number" : 9588 } -->> { "number" : { "$maxKey" : 1 } } on : rs0 Timestamp(1, 2)

再次运行这些命令,以证明chunks正在从rs0迁移到rs1