MongoDB分片介绍与部署

        大家好,MongoDB是一个面向文档的NoSQL数据库,以其灵活性、性能和可扩展性而闻名。而分片(Sharding)是MongoDB提供的一种水平扩展数据的方式,允许将数据分布在多个物理服务器上,以应对大规模数据的存储和处理需求。

前面跟大家分享了关于 MongoDB副本集介绍与部署,可以参考:

MongoDB副本集介绍与部署

一、分片介绍

        分片(shard)是集群中负责管理数据的各个子集的一台或多台服务器。一个分片可以由多台服务器组成。在分片中,不同的服务器负责保存数据的不同部分,它们共同组成了整个数据集。

        为了保证数据在各个分片间的均匀分布,MongoDB会自动在不同的分片之间移动数据子集。这些数据子集的移动是基于片键(shard key)来决定的。

1、分片数据

(1)一分片一区间

        分片最简单的方式就是每个分片负责存储一个区间段的数据,如用户名由4个分片进行存储,由用户名作为分片的依据那么将是如下情况:

        这种方式有一个问题,在数据迁移时,可能会造成级联效应,即如果要将第一分片中的数据均衡,可能要影响很多分片,造成移动的数据量过大,影响整个系统的正常运行。原因很简单,每个分片要保持一区间模式。

(2)一分片多区间

        这种方式可以有效的避免一分片一区间的数据迁移问题,宗旨是每个分片可以存储多个区间的数据。例子,如果[a, f)和[f, n)区间的数据比后面的两个分片都大,需要进行数据移动,则可以将[a, f)分为[a, c)和[c, f),[f, n)分为[f, j)和[j, n),并进行数据移动,则最终成为下面的分片状态:

在添加新分片后,MongoDB可以从每个分片取出部分数据,移动到新分片上。

2、创建块

        在决定如何分配数据时,必须选择一个键来定义数据的块区间,这个键被称为片键(shard key)。片键可以是任意字段或字段的组合。

        在最初的情况下,MongoDB只会创建一个数据块,该数据块的区间覆盖了整个数据集。只有当数据量达到一定程度时,MongoDB才会进行分片。一旦设置了分片配置,就需要指定片键。您可以通过使用命令 sh.shardCollection 来完成这一设置。

3、平衡

        如果存在多个可用的分片,只要块的数量足够多,MongoDB就会将数据迁移到其他分片上。这个迁移过程被称为平衡,由平衡器进程负责执行。

        触发平衡器的条件是:一个分片的块数量必须比最少块的分片多至少9个。此时,块将从拥挤的分片迁移到其他分片,直到各分片达到平衡为止。

        平衡器并不会过于敏感,否则,即使分片之间稍微不平衡,也会频繁触发平衡操作,导致系统资源的过度浪费。

以下是一些方便验证配置的方法:

(1)设置块大小(chunkSize): 可以通过设置块的大小来快速观察数据迁移过程。例如,使用 --chunkSize 1 可以将块的大小设置为1MB。这样,在插入10MB的数据后,就会触发数据迁移。

(2)递增块大小: 可以设置递增的块大小。这样,在创建前十几个块时,MongoDB会自动将块的大小从200MB逐渐降低到64MB。

4、mongos

        mongos是用户与MongoDB分片集群之间的交互点,它充当了用户访问集群的唯一入口,将复杂的处理流程隐藏在后台。简言之,所有对集群的操作都通过mongos服务进行,mongos会将用户的请求转发到相应的分片上去处理。

5、集群中的角色

构建一个MongoDB Sharding Cluster需要三种角色:

(1)Shard Server(分片服务器): 这些是mongod实例,负责存储实际的数据块。在实际生产环境中,一个Shard Server角色通常由多台机器组成一个Replica Set来承担,以防止主机单点故障。

(2)Config Server(配置服务器): 这些也是mongod实例,它们存储了整个集群的元数据,包括Chunk信息等。

(3)Route Server(路由服务器): 这些是mongos实例,充当前端路由,客户端通过它们接入集群。它们让整个集群对客户端看起来像单一的数据库,使得前端应用可以透明地使用集群。

        这三种角色共同协作,构成了一个MongoDB Sharding Cluster,能够实现数据的水平扩展,并在处理大数据量时表现出色。

分片集群的架构:

二、分片配置

        由于项目需要,要部署一个副本集的分片集群,有四个服务器用来部署mongoDB,我们将数据分为三个副本集分片,并分别部署三个config server和三个mongos, 则具体分配如下:

Server 218.30.117.193:
10001        shard1
10002        shard2
10003        shard3
20001        config1
Server 218.30.117.195:
10001        shard1
10002        shard2
10003        shard3
20002        config2
Server 218.30.117.196:
10001        shard1
10002        shard2
10003        shard3
20003        config3
Server 218.30.117.197:
30001        mongos1
30002        mongos2
30003        mongos3

1、启动Config server实例

        配置数据库(Config Server)是存放集群元数据的mongod实例。使用 `--configsvr` 选项可以将一个mongod实例指定为配置服务器。每个配置服务器都保存了集群的完整元数据。

        在生产环境中,必须部署三个配置服务实例,每个实例运行在不同的服务器上,以确保良好的运行时间和数据安全。然而,在测试环境中,你可以在一台独立的服务器上运行三个配置服务实例。

        配置服务实例接收相对较小的流量,并且占用系统资源较少。因此,你可以在运行配置服务实例的系统上同时运行其他实例,以最大程度地利用系统资源。

(1)    为每个配置服务实例创建一个数据目录。默认的情况下,配置服务将数据文件存储在/data/configdb目录下。

(2)    运行三个配置服务实例。使用下面命令:

mongod --configsvr --dbpath <path> --port <port> --logpath <logpath>

如端口为20001,数据存放目录为/mongo-data/config1,日志路径为/mongo-data/config1/log.log,并创建服务进程,命令如下:

mongod --fork --configsvr --port 20001 --dbpath /mongo-data/config1/ --logpath /mongo-data/config1/log.log

2. 启动mongos实例

        Mongos实例是轻量级的,不需要数据目录。你可以在运行其他集群组件的系统上运行一个mongos实例,例如一个应用服务或者一个mongod进程。Mongos的默认端口是27017。

        当你启动一个mongos实例时,你需要在配置文件或者命令行中指定那三个config server的主机名。为了操作的灵活性,最好使用配置服务器的DNS名而不是IP地址。如果你没有使用可解析的主机名,在没有重启每个mongos和mongod实例的情况下,无法更改配置服务器的名称或IP地址。

启动一个mongos实例,命令行如下:

mongos --configdb <config server hostnames>

举个例子,启动一个mongos连接以下配置服务器:

cfg0.example.net
cfg1.example.net
cfg2.example.net

将运行下面的命令:

mongos --configdb cfg0.example.net:27019 cfg1.example.net:27019 cfg2.example.net:27019

3. 向集群中添加分片

一个分片可以是一个单独的mongod或者是一个副本集。在生产环境中,每个分片应该是一个副本集。

(1)    从mongo shell连接到mongos实例上。执行下面的命令:

mongo --host <hostname of machine running mongos> --port <port mongos listens on>

例如:

mongo --host mongos0.example.net --port 27017

(2)    使用sh.addShard()命令将每个分片添加到集群中,如下面的例子所示。为每个分片单独的使用sh.addShard()命令。如果分片是一个副本集,则要指定副本集名并指定组的一个成员。

下面的例子使用了sh.addShard()命令添加一个分片:

  • 通过一个运行在mongodb0.example.net上的27017端口的成员,将一个名为rs1的副本集分片添加到集群中,命令如下:
    sh.addShard(“rs1/mongodb0.example.net:27017”)

    版本2.0.3改变的。

    在这个版本之前,必须指定所有的副本集成员,如:

    sh.addShard( "rs1/mongodb0.example.net:27017,mongodb1.example.net:27017,mongodb2.example.net:27017" )
  • 添加一个运行在mongodb0.example.net服务器上的27017端口的,命令如下:
    sh.addShard( "mongodb0.example.net:27017" )

4. 开启一个数据库的分片功能

        在对一个集合进行分片之前,你必须先启用该集合所在的数据库的分片功能。启用分片功能并不会重新分配数据,但是它确保了集合可以被分片。

        一旦你启用了数据库的分片功能,MongoDB会为其分配一个主分片,使得MongoDB在进行分片之前会将所有的数据保存在该数据库上。

  • 在mongo shell中连接一个mongos实例,使用以下命令语法:
    mongo --host <hostname of machine running mongos> --port <port mongos listens on>
  • 执行sh.enableSharding()方法,指定想要开启分片功能的数据库的名字。使用下面的语法:
    sh.enableSharding("<database>")

    也可以使用enableSharding命令,语法如下:

    db.runCommand( { enableSharding : <database> } )

可以对每个collection开启分片功能。

(1)    决定使用什么作为片键。片键的选择会影响分片的性能。

(2)    如果一个collection已经包含数据,则必须在片键的字段上使用ensureIndex()命令建立一个索引。如果collection是空的,则MongoDB将在sh.shardCollection()阶段建立一个索引。

(3)    通过在mongo shell中执行sh.shardCollection()方法开启一个collection的分片功能。这个方法的使用语法如下:

db.shardCollection(“<database>.<collection>”, shard-key-pattern)

用你的数据库命名空间,由数据库名,一个点和collection的名字组成,替换<database>.<collection>字符串。Shard-key-pattern代表你的片键,你可以使用与一个索引相同的模式。

示例:

sh.shardCollection("records.people", { "zipcode": 1, "name": 1 } )
sh.shardCollection("people.addresses", { "state": 1, "_id": 1 } )
sh.shardCollection("assets.chairs", { "type": 1, "_id": 1 } )

db.alerts.ensureIndex( { _id : "hashed" } )
sh.shardCollection("events.alerts", { "_id": "hashed" } )

这些分片操作按顺序依次表示为:

  • 数据库records 中的People集合使用了片键{ “zipcode” : 1, “name” : 1 }

这个片键通过字段zipcode的值进行数据分配。如果这个有大量相同的值,则会根据name字段的值对块进行分裂。

  • 数据库people的addresses集合使用了片键{ “state” : 1, “_id” : 1 }

这个片键通过字段state的值进行数据分配。如果这个有大量相同的值,则会根据_id字段的值对块进行分裂。

  • 数据库assets的chairs集合使用了片键{ “type” : 1, “_id” : 1 }

这个片键通过字段type的值进行数据分配。如果这个有大量相同的值,则会根据_id字段的值对块进行分裂。

  • 数据库events的alerts集合使用了片键{ “_id” : “hashed” }

在版本2.4中最新出现的。

这个片键通过字段_id的散列值进行数据分配。MongoDB计算_id字段的散列值作为散列索引,它将提供集群中文档的均匀分布。

三、分片部署

1、启动mongod

Server 218.30.117.193:
# /usr/local/mongodb/bin/mongod --fork --shardsvr --port 10001 --dbpath /usr/tmp/shard1/ --logpath /usr/tmp/shard1/log.log --replSet shard1 --rest
# /usr/local/mongodb/bin/mongod --fork --shardsvr --port 10002 --dbpath /usr/tmp/shard2/ --logpath /usr/tmp/shard2/log.log --replSet shard2 --rest
# /usr/local/mongodb/bin/mongod --fork --shardsvr --port 10003 --dbpath /usr/tmp/shard3/ --logpath /usr/tmp/shard3/log.log --replSet shard3 --rest
Server 218.30.117.195:
# /usr/local/mongodb/bin/mongod --fork --shardsvr --port 10001 --dbpath /usr/tmp/shard1/ --logpath /usr/tmp/shard1/log.log --replSet shard1 --rest
# /usr/local/mongodb/bin/mongod --fork --shardsvr --port 10002 --dbpath /usr/tmp/shard2/ --logpath /usr/tmp/shard2/log.log --replSet shard2 --rest
# /usr/local/mongodb/bin/mongod --fork --shardsvr --port 10003 --dbpath /usr/tmp/shard3/ --logpath /usr/tmp/shard3/log.log --replSet shard3 --rest
Server 218.30.117.196:
# /usr/local/mongodb/bin/mongod --fork --shardsvr --port 10001 --dbpath /usr/tmp/shard1/ --logpath /usr/tmp/shard1/log.log --replSet shard1 --rest
# /usr/local/mongodb/bin/mongod --fork --shardsvr --port 10002 --dbpath /usr/tmp/shard2/ --logpath /usr/tmp/shard2/log.log --replSet shard2 --rest
# /usr/local/mongodb/bin/mongod --fork --shardsvr --port 10003 --dbpath /usr/tmp/shard3/ --logpath /usr/tmp/shard3/log.log --replSet shard3 --rest

2、启动config Server

Server 218.30.117.193:
# /usr/local/mongodb/bin/mongod --fork --configsvr --port 20001 --dbpath /usr/tmp/config1/ --logpath /usr/tmp/config1/log.log --rest
Server 218.30.117.195:
# /usr/local/mongodb/bin/mongod --fork --configsvr --port 20002 --dbpath /usr/tmp/config1/ --logpath /usr/tmp/config1/log.log --rest
Server 218.30.117.196:
# /usr/local/mongodb/bin/mongod --fork --configsvr --port 20003 --dbpath /usr/tmp/config1/ --logpath /usr/tmp/config1/log.log --rest

3、启动mongos

这里为了方便的看到分片过程,将chunkSize设置为1,也就是每个块大小为1MB。

218.30.117.197:
# /usr/local/mongodb/bin/mongos --fork --port 30001 --logpath /usr/tmp/route1/log.log --chunkSize 1 --configdb 218.30.117.193:20001,218.30.117.195:20002,218.30.117.196:20003
# /usr/local/mongodb/bin/mongos --fork --port 30002 --logpath /usr/tmp/route2/log.log --chunkSize 1 --configdb 218.30.117.193:20001,218.30.117.195:20002,218.30.117.196:20003
# /usr/local/mongodb/bin/mongos --fork --port 30003 --logpath /usr/tmp/route3/log.log --chunkSize 1 --configdb 218.30.117.193:20001,218.30.117.195:20002,218.30.117.196:20003

4、在mongod上配置副本集

先连接到某个副本集的成员上,然后初始化副本集配置:

连接到218.30.117.193:10001上初始化副本集shard1:

# /usr/local/mongodb/bin/mongo 218.30.117.193:10001/admin
MongoDB shell version: 2.4.2
connecting to: 218.30.117.193:10001/admin
> config={_id:'shard1', members:[{_id:0, host:'218.30.117.193:10001'}, {_id:1, host:'218.30.117.195:10001'}, {_id:2, host:'218.30.117.196:10001'}]}
> rs.initiate(config)

连接到218.30.117.195:10002上初始化副本集shard2:

# /usr/local/mongodb/bin/mongo 218.30.117.195:10002/admin
MongoDB shell version: 2.4.2
connecting to: 218.30.117.195:10002/admin
> config={_id:'shard2', members:[{_id:0, host:'218.30.117.193:10002'}, {_id:1, host:'218.30.117.195:10002'}, {_id:2, host:'218.30.117.196:10002'}]}
> rs.initiate(config)

连接到218.30.117.196:10003上初始化副本集shard3:

# /usr/local/mongodb/bin/mongo 218.30.117.196:10003/admin
MongoDB shell version: 2.4.2
connecting to: 218.30.117.196:10003/admin
> config={_id:'shard3', members:[{_id:0, host:'218.30.117.193:10003'}, {_id:1, host:'218.30.117.195:10003'}, {_id:2, host:'218.30.117.196:10003'}]}
> rs.initiate(config)

可以通过rs.status()命令查看副本集配置结果:

> rs.status()
{
    "set" : "shard3",
    "date" : ISODate("2013-05-14T17:44:05Z"),
    "myState" : 1,
    "members" : [
        {
            "_id" : 0,
            "name" : "218.30.117.193:10003",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 147,
            "optime" : {
                "t" : 1368553298,
                "i" : 1
            },
            "optimeDate" : ISODate("2013-05-14T17:41:38Z"),
            "lastHeartbeat" : ISODate("2013-05-14T17:44:03Z"),
            "lastHeartbeatRecv" : ISODate("2013-05-14T17:44:05Z"),
            "pingMs" : 0,
            "syncingTo" : "218.30.117.196:10003"
        },
        {
            "_id" : 1,
            "name" : "218.30.117.195:10003",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 147,
            "optime" : {
                "t" : 1368553298,
                "i" : 1
            },
            "optimeDate" : ISODate("2013-05-14T17:41:38Z"),
            "lastHeartbeat" : ISODate("2013-05-14T17:44:03Z"),
            "lastHeartbeatRecv" : ISODate("2013-05-14T17:44:03Z"),
            "pingMs" : 1,
            "syncingTo" : "218.30.117.196:10003"
        },
        {
            "_id" : 2,
            "name" : "218.30.117.196:10003",
            "health" : 1,
            "state" : 1,
            "stateStr" : "PRIMARY",
            "uptime" : 1109,
            "optime" : {
                "t" : 1368553298,
                "i" : 1
            },
            "optimeDate" : ISODate("2013-05-14T17:41:38Z"),
            "self" : true
        }
    ],
    "ok" : 1
}

5、向集群添加副本集分片

先通过mongo shell连接到mongos实例:

# /usr/local/mongodb/bin/mongo 218.30.117.197:30001/admin
MongoDB shell version: 2.4.2
connecting to: 218.30.117.197:30001/admin
mongos> db.runCommand({addshard:"shard1/218.30.117.193:10001", name:"ShardSet1"})
{ "shardAdded" : "ShardSet1", "ok" : 1 }
mongos> db.runCommand({addshard:"shard2/218.30.117.195:10002", name:"ShardSet2"})
{ "shardAdded" : "ShardSet2", "ok" : 1 }
mongos> db.runCommand({addshard:"shard3/218.30.117.195:10003", name:"ShardSet3"})
{ "shardAdded" : "ShardSet3", "ok" : 1 }

通过db.runCommand({listshards: 1})查看分片集群的信息:

mongos> db.runCommand({listshards: 1}) 
{
    "shards" : [
        {
            "_id" : "ShardSet1",
            "host" : "shard1/218.30.117.193:10001,218.30.117.195:10001,218.30.117.196:10001"
        },
        {
            "_id" : "ShardSet2",
            "host" : "shard2/218.30.117.193:10002,218.30.117.195:10002,218.30.117.196:10002"
        },
        {
            "_id" : "ShardSet3",
            "host" : "shard3/218.30.117.193:10003,218.30.117.195:10003,218.30.117.196:10003"
        }
    ],
    "ok" : 1
}

6、开启数据库的分片功能

我们的数据库名为page_db,则命令如下:

mongos> sh.enableSharding("page_db")
{ "ok" : 1 } 

7、开启数据库中users集合的分片功能,并指定_id的散列值组作为片键

mongos> sh.shardCollection("page_db.users", {_id : "hashed"})
{ "collectionsharded" : "page_db.users", "ok" : 1 }

总结:

分片功能在少数据量时没有必要,只是增加了架构的复杂性。但如果数据量大,访问量大的情况下,分片还是很有必要的。

  • 27
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
MongoDB分片部署是通过将数据分布在多个服务器上来实现水平扩展的一种方式。下面是MongoDB分片部署的一般步骤: 1. 安装和配置MongoDB:在每个分片服务器上安装并配置MongoDB,确保它们可以相互通信。 2. 配置路由器(mongos):MongoDB分片集群需要一个路由器来处理客户端请求并将数据路由到正确的分片。在其中一个服务器上启动mongos进程,并将其配置为连接到分片服务器和配置服务器。 3. 配置配置服务器(config servers):配置服务器存储了整个集群的元数据信息,包括分片键和分片信息。至少需要3个配置服务器来保证高可用性。在每个配置服务器上启动mongod进程,并将它们组成一个复制集。 4. 创建分片集合(sharded collection):选择一个分片键,该键将用于将数据划分到不同的分片中。通过创建一个分片集合来启用分片功能,并指定要用作分片键的字段。 5. 添加分片(shard):将每个分片服务器添加到集群中。可以使用“sh.addShard()”命令将分片服务器添加到路由器中。 6. 启用分片集合:使用“sh.enableSharding()”命令启用分片集合,并指定要分片的数据库和集合。 7. 设定初始的分片数据位置(optional):可以使用“sh.shardCollection()”命令手动指定初始的分片数据位置。 完成上述步骤后,MongoDB集群就可以进行分片部署了。在添加更多数据时,MongoDB会自动将数据根据分片键路由到正确的分片上。 请注意,以上是一般的步骤,具体的配置可能会因环境和需求而有所不同。建议在进行分片部署前仔细阅读MongoDB官方文档,并根据实际情况进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

寒秋丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值