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.分片的主要内容,如果未能解决你的问题,请参考以下文章

19.分片

MySQL(19) Mycat分片(分库分表)配置

mangodb—分片和副本集架构部署

MongoDB——从集群中删除分片,根据官网教程实际操作记录

mycat分片规则之分片枚举(sharding-by-intinfile)

Oracle分布式分片技术——实现两主机上的Oracle19c数据库(CentOS7与windows10)之间建立分布式数据库管理