19.分片
Posted 大数据小小罗
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了19.分片相关的知识,希望对你有一定的参考价值。
分片就是将数据库分布在多台服务器上
为什么会用到分片?
1 机器的磁盘空间不足
2 单个的mongoDB服务器已经不能满足大量的插入操作
3 想通过把大数据放到内存中来提高性能
1.组成介绍:
1.分片
MongoDB分片集群将数据分布在一个或多个分片上。每个分片都部署成一个MongoDB副本集,该副本集保存了集群整体数据的一部分。因为每个分片都是一个副本集没所以它们拥有自己的复制机制,能够自动进行故障转移。直接连接单个分片只能查看到部分数据。
2.mongos路由器
用于连接整个集群,它将所有的读写请求指引到合适的分片上。这是一个前端路由,客户端由此接入,然后询问 Config Servers 需要到哪个 Shard 上查询或保存记录,再连接相应的 Shard 进行操作,最后将结果返回给客户端。客户端只需要将原本发给 mongod 的查询或更新请求原封不动地发给 Routing Process,而不必关心所操作的记录
存储在哪个 Shard 上。
3.配置服务器
持久化分片集群的元数据。这些数据包括:全局集群配置;每个数据库、集合和特定范围数据的位置;一份变更记录,保存了数据在分片之间进行迁移的历史信息。
2示例
实现一个这样架构的分片集群:
s0Server:18000
s1Server:18001
configServer:18200
route:18010
2.1 启动 Shard Server
--创建数据目录
E:\\MyProgram\\MongodbDATA\\09\\s0
E:\\MyProgram\\MongodbDATA\\09\\s1
E:\\MyProgram\\MongodbDATA\\09\\c
编辑配置文件:
s0Server.conf
dbpath=E:\\MyProgram\\MongodbDATA\\09\\s0
bind_ip = 127.0.0.1
port=18000
shardsvr=true
s1Server.conf
dbpath=E:\\MyProgram\\MongodbDATA\\09\\s1
bind_ip = 127.0.0.1
port=18001
shardsvr=true
启动 Shard Server 实例 s0Server:
mongod --config s0Server.conf
启动 Shard Server 实例 s1Server:
mongod --config s1Server.conf
2.2 启动 Config Server
1.创建数据目录:
2.配置文件configServer.conf
configsvr=true
dbpath = E:\\MyProgram\\MongodbDATA\\09\\c
port = 18200
bind_ip = 127.0.0.1
3.启动 Config Server 实例:
mongod --config configServer.conf
2.3 启动 Route Process
启动 Route Server 实例:
mongos --port 18010 --configdb 127.0.0.1:18200 --chunkSize=1
mongos 启动参数中, chunkSize 这一项是用来指定 chunk 的大小的,单位是 MB,默认大小
为 200MB,为了方便测试 Sharding 效果,我们把 chunkSize 指定为 1MB。
2.4 配置 Sharding
接下来,我们使用 MongoDB Shell 登录到 mongos,添加 Shard 节点
[root@localhost ~]# /Apps/mongo/bin/mongo admin --port 40000 --此操作需要连接 admin 库
MongoDB shell version: 1.8.1
connecting to: 127.0.0.1:40000/admin
> db.runCommand( addshard:"localhost:18000" ) --添加 Shard Server1
"shardAdded" : "shard0000", "ok" : 1
> db.runCommand( addshard:"localhost:18001" ) --添加 Shard Server2
"shardAdded" : "shard0001", "ok" : 1
> db.runCommand( enablesharding:"test" ) --设置分片存储的数据库
"ok" : 1
> db.runCommand( shardcollection: "test.users", key: _id:1 ) --设置分片的集合名称,且必须指定 Shard Key,系统会自动创建索引
"collectionsharded" : "test.users", "ok" : 1
>
2.5 验证 Sharding 正常工作
我们已经对 test.users 表进行了分片的设置,下面我们们插入50w条数据看一下结果
> use test
switched to db test
> for (var i = 1; i <= 500000; i++) db.users.insert(age:i, name:"tom", addr:"Beijing",country:"China")
>mongos> db.users.stats()
"sharded" : true, ##说明此表已经被分片了
"flags" : 1,
"ns" : "test.users",
"count" : 500000,
"numExtents" : 16,
"size" : 44000016,
"storageSize" : 66666496,
"totalIndexSize" : 16253888,
"indexSizes" :
"_id_" : 16253888
,
"avgObjSize" : 88.000032,
"nindexes" : 1,
"nchunks" : 5,
"shards" :
"shard0000" : ##第一个分片大约25M
"ns" : "test.users",
"count" : 289589,
"size" : 25483840,
"avgObjSize" : 88.0000276253587,
"storageSize" : 33333248,
"numExtents" : 8,
"nindexes" : 1,
"lastExtentSize" : 12083200,
"paddingFactor" : 1,
"flags" : 1,
"totalIndexSize" : 9410576,
"indexSizes" :
"_id_" : 9410576
,
"ok" : 1
,
"shard0001" : ##第二个分片大约18M
"ns" : "test.users",
"count" : 210411,
"size" : 18516176,
"avgObjSize" : 88.00003802082591,
"storageSize" : 33333248,
"numExtents" : 8,
"nindexes" : 1,
"lastExtentSize" : 12083200,
"paddingFactor" : 1,
"flags" : 1,
"totalIndexSize" : 6843312,
"indexSizes" :
"_id_" : 6843312
,
"ok" : 1
,
"ok" : 1
2.6我们看一下磁盘上的物理文件情况
看上述结果,表明 test.users 集合已经被分片处理了,但是通过 mongos 路由,我们并感觉不到是数据存放在哪个 shard 的 chunk 上的,这就是 MongoDB 用户体验上的一个优势,即对用户是透明的。
3管理维护 Sharding
3.1 列出所有的 Shard Server
> use admin
> db.runCommand( listshards: 1 ) --列出所有的 Shard Server
"shards" : [
"_id" : "shard0000",
"host" : "localhost:18000"
,
"_id" : "shard0001",
"host" : "localhost:18001"
],
"ok" : 1
3.2 查看 Sharding 信息
> printShardingStatus() --查看 Sharding 信息
--- Sharding Status ---
sharding version: "_id" : 1, "version" : 3
shards:
"_id" : "shard0000", "host" : "localhost:18000"
"_id" : "shard0001", "host" : "localhost:18001"
databases:
"_id" : "admin", "partitioned" : false, "primary" : "config"
"_id" : "test", "partitioned" : true, "primary" : "shard0000"
test.users chunks:
shard0000 4
shard0001 1
"_id" : $minKey : 1 -->> "_id" : ObjectId("585
fbdc22730e421633a26a8") on : shard0000 "t" : 2000, "i" : 1
"_id" : ObjectId("585fbdc22730e421633a26a8") -->>
"_id" : ObjectId("585fbdc72730e421633a3f3c") on : shard0000 "t" : 1000, "i"
: 3
"_id" : ObjectId("585fbdc72730e421633a3f3c") -->>
"_id" : ObjectId("585fbdea2730e421633d7527") on : shard0001 "t" : 3000, "i"
: 1
"_id" : ObjectId("585fbdea2730e421633d7527") -->>
"_id" : ObjectId("585fbe432730e4216340ac0c") on : shard0000 "t" : 3000, "i"
: 2
"_id" : ObjectId("585fbe432730e4216340ac0c") -->>
"_id" : $maxKey : 1 on : shard0000 "t" : 3000, "i" : 3
3.3 判断是否是 Sharding
> db.runCommand( isdbgrid:1 )
"isdbgrid" : 1, "hostname" : "acer", "ok" : 1
>
3.4 对现有的表进行 Sharding
刚才我们是对表 test.users 进行分片了,下面我们将对库中现有的未分片的表 test.users_2 进行分片处理
先建一个表test.users2:
> use test
switched to db test
插入数据:
> for (var i = 1; i <= 500000; i++) db.users.insert(age:i, name:"tom", addr:"Beijing",country:"China")
表最初状态如下,可以看出他没有被分片过:
> db.users2.stats()
"ns" : "test.users_2",
"sharded" : false,
"primary" : "shard0000",
"ns" : "test.users_2",
"count" : 500000,
"size" : 48000016,
"avgObjSize" : 96.000032,
"storageSize" : 61875968,
"numExtents" : 11,
"nindexes" : 1,
"lastExtentSize" : 15001856,
"paddingFactor" : 1,
"flags" : 1,
"totalIndexSize" : 20807680,
"indexSizes" :
"_id_" : 20807680
,
"ok" : 1
对其进行分片处理:
首先切换到admin用户
> use admin
switched to db admin
执行分片命令:传入参数:1.要被分片的文档 2.指定片键
> db.runCommand( shardcollection: "test.users2", key: _id:1 )
"collectionsharded" : "test.users2", "ok" : 1
再次查看分片后的表的状态,可以看到它已经被我们分片了
> use test
switched to db test
> db.users2.stats()
"sharded" : true,
"ns" : "test.users_2",
"count" : 505462,
……
"shards" :
"shard0000" :
"ns" : "test.users2",
……
"ok" : 1
,
"shard0001" :
"ns" : "test.users2",
……
"ok" : 1
,
"ok" : 1
>
3.5 新增分片服务器 Shard Server
刚才我们演示的是新增分片表,接下来我们演示如何新增 Shard Server
启动一个新 Shard Server 进程
[root@localhost ~]# mkdir /data/shard/s2
[root@localhost ~]# /Apps/mongo/bin/mongod --shardsvr --port 20002 --dbpath /data/shard/s2
--fork --logpath /data/shard/log/s2.log --directoryperdb
all output going to: /data/shard/log/s2.log
forked process: 6772
配置新 Shard Server
[root@localhost ~]# /Apps/mongo/bin/mongo admin --port 40000
MongoDB shell version: 1.8.1
connecting to: 127.0.0.1:40000/admin
## 添加分片
> db.runCommand( addshard:"localhost:20002" )
"shardAdded" : "shard0002", "ok" : 1
> printShardingStatus()
--- Sharding Status ---
sharding version: "_id" : 1, "version" : 3
shards:
"_id" : "shard0000", "host" : "localhost:20000"
"_id" : "shard0001", "host" : "localhost:20001"
"_id" : "shard0002", "host" : "localhost:20002" #新增的Shard Server
databases:
"_id" : "admin", "partitioned" : false, "primary" : "config"
"_id" : "test", "partitioned" : true, "primary" : "shard0000"
test.users chunks:
shard0002 2
shard0000 21
shard0001 21
too many chunksn to print, use verbose if you want to force print
test.users_2 chunks:
shard0001 46
shard0002 1
shard0000 45
too many chunksn to print, use verbose if you want to force print
查看分片表状态,以验证新 Shard Server
> use test
switched to db test
> db.users_2.stats()
"sharded" : true,
"ns" : "test.users_2",
……
"shard0002" : ## 新的 Shard Server 已有数据
"ns" : "test.users_2",
"count" : 21848,
"size" : 2097408,
"avgObjSize" : 96,
"storageSize" : 2793472,
"numExtents" : 5,
"nindexes" : 1,
"lastExtentSize" : 2097152,
"paddingFactor" : 1,
"flags" : 1,
"totalIndexSize" : 1277952,
"indexSizes" :
"_id_" : 1277952
,
"ok" : 1
,
"ok" : 1
>
3.6 移除 Shard Server
有些时候有于硬件资源有限,所以我们不得不进行一些回收工作,下面我们就要将刚刚启用的 Shard Server 回收
系统首先会将在这个即将被移除的 Shard Server 上的数据先平均分配到其它的 Shard Server 上,然后最终在将这个 Shard Server 踢下线, 我们需要不停的调用db.runCommand(“removeshard” : “localhost:18002”);来观察这个移除操作进行到哪里了:
> use admin
switched to db admin
> db.runCommand("removeshard" : "localhost:18002");
"msg" : "draining started successfully",
"state" : "started", ##启动
"shard" : "shard0002",
"ok" : 1
> db.runCommand("removeshard" : "localhost:18002");
"msg" : "draining ongoing",
"state" : "ongoing", ##即将开始
"remaining" :
"chunks" : NumberLong(44), ##块的个数
"dbs" : NumberLong(0)
,
"ok" : 1
……
> db.runCommand("removeshard" : "localhost:18002");
"msg" : "draining ongoing",
"state" : "ongoing",
"remaining" :
"chunks" : NumberLong(1),
"dbs" : NumberLong(0)
,
"ok" : 1
> db.runCommand("removeshard" : "localhost:18002");
"msg" : "removeshard completed successfully",
"state" : "completed",
"shard" : "shard0002",
"ok" : 1
> db.runCommand("removeshard" : "localhost:18002");
"assertion" : "can't find shard for: localhost:20002",
"assertionCode" : 13129,
"errmsg" : "db assertion failure",
"ok" : 0
最终移除后,当我们再次调用 db.runCommand(“removeshard” : “localhost:18002”);的时候系统
会报错,已便通知我们不存在 18002 这个端口的 Shard Server 了,因为它已经被移除掉了。
接下来我们看一下表中的数据分布:
> use test
switched to db test
> db.users2.stats()
"sharded" : true,
"ns" : "test.users_2",
"count" : 500000,
"size" : 48000000,
"avgObjSize" : 96,
"storageSize" : 95203584,
"nindexes" : 1,
"nchunks" : 92,
"shards" :
"shard0000" :
"ns" : "test.users_2",
"count" : 248749,
"size" : 23879904,
"avgObjSize" : 96,
"storageSize" : 61875968,
"numExtents" : 11,
"nindexes" : 1,
"lastExtentSize" : 15001856,
"paddingFactor" : 1,
"flags" : 1,
"totalIndexSize" : 13033472,
"indexSizes" :
"_id_" : 13033472
,
"ok" : 1
,
"shard0001" :
"ns" : "test.users_2",
"count" : 251251,
"size" : 24120096,
"avgObjSize" : 96,
"storageSize" : 33327616,
"numExtents" : 8,
"nindexes" : 1,
"lastExtentSize" : 12079360,
"paddingFactor" : 1,
"flags" : 1,
"totalIndexSize" : 10469376,
"indexSizes" :
"_id_" : 10469376
,
"ok" : 1
,
"ok" : 1
可以看出数据又被平均分配到了另外 2 台 Shard Server 上了,对业务没什么特别大的影响。
我们可以发现,当我们新增 Shard Server 后数据自动分布到了新 Shard 上,这是由 MongoDB 内部自已实现的。
实际生产环境中最常用的结构–副本集+分片(Replica sets + Sharding)
MongoDB Auto-Sharding 解决了海量存储和动态扩容的问题,但离实际生产环境所需的高可靠、高可用还有些距离,所以有了” Replica Sets + Sharding”的解决方案:
Shard:
使用 Replica Sets,确保每个数据节点都具有备份、自动容错转移、自动恢复能力。
Config:
使用 3 个配置服务器,确保元数据完整性
Route:
使用 3 个路由进程,实现负载平衡,提高客户端接入性能
以下我们配置一个 Replica Sets + Sharding 的环境,架构图如下:
以上是关于19.分片的主要内容,如果未能解决你的问题,请参考以下文章
MongoDB——从集群中删除分片,根据官网教程实际操作记录
mycat分片规则之分片枚举(sharding-by-intinfile)
Oracle分布式分片技术——实现两主机上的Oracle19c数据库(CentOS7与windows10)之间建立分布式数据库管理