MongoDB学习笔记九:分片

分片(sharding)是指将数据拆分,将其分散存在不同的机器上的过程。有事也用分区(partitioning)来表示这个概念。将数据分散到不同的机器上,不需要功能强大的大型计算机既可以存储更多的数据,处理更大的负载。
『MongoDB中的自动分片』
MongoDB在分片之前要运行一个路由进程,该进程名为mongos。这个路由器知道多有数据的存放位置,所以应用可以连接它来正常发送请求。mongos对应用隐藏了分片的细节。
何时分片?
    ·     机器的磁盘不够用了。
    ·     单个mongod已经不能满足写数据的性能需要了。
    ·     想将大量数据放在内存中提高性能。
『片键』
设置分片时,需要从集合里面选一个键,用改键的值作为数据拆分的依据。这个键成为片键(shard     key)。
随着添加(或者删除)片,MongoDB会重新平衡数据,使每片的流量都比较均匀,数据量也在合理范围内。
『将已有的集合分片』
假设有个存储日志的集合,现在要分片。我们开启分片功能,然后告诉MongoDB用"timestamp"作为片键,就把所有数据放到了一个片上。可以随意插入数据,但总会是在一个片上。
而后,增加一个片。这个片建好并运行了以后,MongoDB就会把集合拆分成两半,称为块。每个块中包含片键值在一定范围内的所有文档,所以就假设其中一块包含时间戳在2003年6月26日以前的文档,另一块含有2003年6月27日以后的文档。其中一块会被移动到新片上。
如果新文档的时间戳在2003年6月27日之前,则添加到第一个块,否则就加到另一个块。
【建立分片】
建立分片有两步:启动实际的服务器,然后决定怎么切分数据。
分片一般会有3个组成部分:
    ·     片
    片就是保存子集合数据的容器。片可以是单个的mongod服务器(开发和测试用),也可以是副本集(生产用)。所以,几遍一片内有多台服务器,也只能有一个主服务器,其他的服务器保存相同的数据。
    ·     mongos
    mongos就是MongoDB各版本中都配的路由器进程。它路由所有请求,然后将结果聚合。它本身并不存储数据或者配置信息(但会缓存配置服务器的信息)。
    ·     配置服务器
    配置服务器存储了集群的配置信息:数据和片的对应关系。mongos不永久存放数据,所以需要个地方存放分片配置。他会从配置服务器获取同步数据。
『启动服务器』
首先要启动配置服务器和mongos。配置服务器需要最先启动,因为mongos会用到其上的配置信息。配置服务器的启动就像普通mongod一样。
$     mkdir     -p     ~/dbs/config
$     ./mongod     --dbpath     ~/dbs/config     --port     20000
配置服务器不需要很多空间和资源(200MB实际数据大约占用1KB的配置空间)。
现在就可以建立mongos进程,以供应用程序连接。这种路由服务器连数据目录都不需要,但一定要指明配置服务器的位置:
$     ./mongos     --port     30000     --configdb     localhost:20000
分片管理通常是通过mongos完成的。
添加片
片就是普通的mongod实例(或者副本集):
$     mkdir     -p     ~/dbs/shard1
$     ./mongod     --dbpath     ~/dbs/shard1     --port     10000
现在连接刚才启动的mongos,为集群添加一个片。启动shell,连接mongos:
$     ./mongo     localhost:30000/admin
MongoDB     shell     version:     1.6.0
url:     localhost:30000/adminconnecting     to     localhost:30000/admin
type     "help"     for     help
>
确定连接的是mongos而不是mongod后,就可以通过addshard命令添加片了:
>     db.runCommand({addShard     :     "localhost:10000",     allowLocal     :     true})
{
    "added"     :     "localhost:10000",
    "ok"     :     true
}
挡在localhost上运行分片时,得设定"allowLocal"键。MongoDB尽量避免由于错误配置,将集群配置到本地,所以得让它知道这仅仅是开发,而且我们很清楚自己在做什么。如果实在生产环境中,则要将其部署在不同的机器上。
想添加片的时候,就运行addShard。MongoDB会负责将片集成到集群。
『切分数据』
MongoDB不会将存储的每一条数据都直接发布,得先在数据库和集合的级别将分片功能打开。下面的例子将以"_id"为急转切分foo数据库的bar集合。首先得开启foo的分片功能:
>     db.runCommand({"enablesharding"     :     "foo"})
对数据库分片后,其内部的集合便会存储到不同的片上,同时也是对这些集合分片的前置条件。
在数据库的级别启动了分片以后,就可以使用shardCollection命令来对集合进行分片了:
>     db.runCommand({"shardCollection"     :     "foo.bar",     "key"     :     {"_id"     :     1}})
这样集合就按照"_id"分片了,在添加数据,就会依据"_id"的值自动分散到各个片上。
【生产配置】
成功地构建分片需要如下条件:
    ·     多个配置服务器。
    ·     多个mongos服务器。
    ·     每个片都是副本集。
    ·     正确设置w。
例:设置3个配置服务器:
$     mkdir     -p     ~/dbs/config1     ~/dbs/config2     ~/dbs/config3
$     ./mongod     --dbpath     ~/dbs/config1     --port     20001
$     ./mongod     --dbpath     ~/dbs/config2     --port     20002
$     ./mongod     --dbpath     ~/dbs/config3     --port     20003
然后,启动mongos的时候应将其连接到这3个配置服务器:
$     ./mongos     --configdb     localhost:20001,localhost:20002,localhost:20003
配置服务器使用的是两步提交机制——而不是普通MongoDB的异步复制——来维护集群配置的不同副本。这样能保证集群状态的一致性。这也意味着,某台配置服务器宕掉了以后,集群配置信息将是只读的。客户端还能够读写,但是只有所有配置服务器备份了以后才能重新均衡数据。    
mongos的数量不受限制。建议针对一个应用服务器只运行一个mongos进程。这样每个应用服务器就可以与mongos进行本地回鹘,如果服务器不工作了,就不会有应用试图与不在的mongos通话了。
『健壮的片』
生产环境中,每个片都应是副本集。这样单个的服务器坏了,就不会导致整个片失效。用addshard命令就可以将副本集作为片添加。添加时只要指定副本集的名字和种子就好了。
比如要添加副本集foo,其中包含一个服务器prod.example.com:27017(还有别的服务器),就可以使用下列命令将其添加到集群里:
>     db.runCommand({"addshard"     :     "foo/prod.example.com:27017"})
如果prod.example.com挂了,mongos会知道它所连接的是一个副本集,并会使用新的主节点。
【管理分片】
分片信息主要存放在config数据库上,这样就能被任何连接到mongos的进程访问到了。
『配置集合』
下几节的代码都假设已经在shell中连接了mongos,并且已经运行了use     config。
⒈片
可以在shards集合中查到所有的片:
>     db.shards.find()
{     "_id"     :     "shard0",     "host"     :     "localhost:10000"     }
{     "_id"     :     "shard1",     "host"     :     "localhost:10001"     }
⒉数据库
databases集合含有已经在片上的数据库列表和一些相关信息:
>     db.databases.find()
{     "_id"     :     "admin",     "partitioned"     :     false,     "primary"     :     "config"     }
{     "_id"     :     "foo",     "partitioned"     :     false,     "primary"     :     "shard1"     }
{     "_id"     :     "x",     "partitioned"     :     false,     "primary"     :     "shard0"     }
{
    "_id"     :     "test",
    "partitioned"     :     true,
    "primary"     :     "shard0",
    "sharded"     :     {
        "test.foo"     :     {
            "key"     :     {"x"     :     1},
            "unique"     :     false
        }
    }
}
这里是全部可用的数据库和一些基本信息。
    ·     "_id",字符串
    "_id"表示数据名。
    ·     "partitioned",布尔型
    如果为true,则表示已经启用分片功能。
    ·     "primary",字符串
    这个值与片的"_id"相对应,表明这个数据库的“大本营”在哪里。不论分片与否,数据库总是会有个大本营的。要是分片了的话,创建数据库时会随机选择一个片。也就是说,大本营是开始创建数据库文件的位置。虽然分片时数据库也会用到很多别的服务器,但是会从这个片开始。    
⒊块
块信息保存在chunks集合中。它有很多有趣的东西,也可以看到数据到底是怎么切分到集群的:
>     db.chunks.find()
{
    "_id"     :     "test.foo-x_MinKey",
    "lastmod"     :     {     "t"     :     1276636243000,     "i"     :     1     },
    "ns"     :     "test.foo",
    "min"     :     {
        "x"     :     {     $minKey     :     1     }
    },
    "max"     :     {
        "x"     :     {     $maxKey     :     1     }
    },
    "shard"     :     "shard0"
}
单块的集合就是这样的:块的范围从-∞(MinKey)到∞(MaxKey)。

原文地址:https://www.cnblogs.com/answernotfound/p/mongodbnote9.html