Fanr

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

9.分片(Sharding)

Mongodb Manual阅读笔记:CH2 Mongodb CRUD 操作
Mongodb Manual阅读笔记:CH3 数据模型(Data Models)
Mongodb Manual阅读笔记:CH4 管理
Mongodb Manual阅读笔记:CH5 安全性
Mongodb Manual阅读笔记:CH6 聚合
Mongodb Manual阅读笔记:CH7 索引
Mongodb Manual阅读笔记:CH8 复制集
Mongodb Manual阅读笔记:CH9 Sharding

 

随着数据增长,shard是多机器处理数据存储的方式。shard是横向扩展的解决方案。

9.分片(Sharding)1

9.1 Sharding说明... 1

9.1.1 Shard的目的... 1

9.1.2 Mongodb中的Shard. 1

9.1.3数据分区... 1

9.1.3.1 Shard Keys. 1

9.1.3.2 Range分区... 1

9.1.3.3 Hash分区... 1

9.1.3.4 Range分区和Hash分区的性能区别... 1

9.1.4 维护数据均衡发布... 1

9.1.4.1 分离(Splitting)1

9.1.4.2均衡(Balancing)1

9.1.4.3 增加和删除Shard. 1

9.2 Sharding 概述... 1

9.2.1 Shard集群组件... 1

9.2.1.1 Shards. 1

9.2.1.2 Config服务... 1

9.2.2 Shard集群体系结构... 1

9.2.2.1 Shard集群要求... 1

9.2.2.2生产环境集群结构... 1

9.2.2.3测试环境的体系结构... 1

9.2.3 Shard集群特性... 1

9.2.3.1 Shard Key. 1

9.2.3.2 Shard集群高可用性... 1

9.2.3.3 Shard集群查询路由... 1

9.2.4 Shard机制... 1

9.2.4.1 Shard Collection均衡... 1

9.2.4.2 ShardChunk迁移... 1

9.2.4.3 Shard集群下Chunk的分离... 1

9.2.4.4 Shard Key索引... 1

9.2.4.5Shard集群元数据... 1

9.3 Shard集群教程... 1

9.3.1 Shard集群部署教程... 1

9.3.1.1部署shard集群... 1

9.3.1.2考虑Shard Key. 1

9.3.1.3使用Hash Shard Key. 1

9.3.1.4 Shard集群的认证... 1

9.3.1.5添加Shard到集群... 1

9.3.1.6为生产环境部署3Config服务... 1

9.3.1.7把复制集转化为shard集群... 1

9.3.1.8shard集群转化为复制集... 1

9.3.2 Shard集群维护教程... 1

9.3.2.1查看集群配置... 1

9.3.2.2使用相同的hostname迁移config. 1

9.3.2.3在不同HostName之前迁移config. 1

9.3.2.4替换一个Config服务... 1

9.3.2.5迁移集群到不同的硬件环境... 1

9.3.2.6备份集群元数据... 1

9.3.2.7配置均衡器进程行为... 1

9.3.2.8管理均衡器... 1

9.3.2.9删除Shard集群中的Shard. 1

9.3.3 Shard集群的数据管理... 1

9.3.3.1创建Chunks. 1

9.3.3.2 Split Chunk. 1

9.3.3.3迁移Chunk. 1

9.3.3.4修改Chunk的大小... 1

9.3.3.5 Tag意向Sharding. 1

9.3.3.6管理Shard Tag. 1

9.3.3.7 shard集群强制唯一键... 1

9.3.3.8 Shard GridFS数据存储... 1

9.3.4 Shard集群Troubleshoot. 1

9.3.4.1 Config数据库错误字符串... 1

9.3.4.2 因为老的config数据导致游标错误... 1

9.3.4.3在移动config服务避免下线... 1

9.4 Shard Reference. 1

 

9.1 Sharding说明

9.1.1 Shard的目的

当数据库数据增大,应用程序高吞吐量会对单服务的能力进行挑战。查询过大cpu使用过大,数据过大要要求存储能力,working set 过大要求RAMIO能力。

为了解决这个问题,有2个基本的方案:水平扩展,垂直扩展。

水平扩展:添加更多的cpu,存储资源来这更加处理能力。大cpu大内存的设备价格会远远大于小设备。

Sharding:是一种水平扩展,把数据分片到各个设备上。每个分片都是一个独立的数据库。

sharding处理大数据,大吞吐量的好处:

1.减少了在每个shard上的操作

2.减少了每个shard上的数据保存量。

9.1.2 Mongodb中的Shard

shard集群由以下几个组件:shardquery routersconfig server

Shard:用来存储数据。提供高可用和数据一致性,在生产环境下一个shard是一个复制集

Query Routers:或者mongos实例,是客户端的接口然后在合适的shard中型操作然后返回数据。对于shard集群可以包含多余一个router来分流客户端请求。一个客户端发送请求到一个router,大多数shard集群由很多query router

Config Server:保存集群元数据,query router根据config server上的元数据来决定路由到哪个shard

9.1.3数据分区

mongodb分发数据或者分配是在collection级别的,同归shard keycollection进行分片。

9.1.3.1 Shard Keys

Shard Keys必须每个文档都有,并且要不是索引的字段,要不是组合索引的字段。mongodbshard key划分为chunks,然后发布这些chunk到各个shard。可以使用range分区也可以是hash分区。

9.1.3.2 Range分区

Mongodb通过shard key把数据分为若干个区间。给定一个Rangekey近的理论上在同一个文档上。

9.1.3.3 Hash分区

hash分区是根据文档中的字段计算hash,然后使用这些hash来创建chunk。那么即使shard key值相近也可能不在同一个chunk中。

9.1.3.4 Range分区和Hash分区的性能区别

对于Range分区,区间查询更加有效,路由可以很容易的决定哪些chunk可以覆盖这些查询,然后路由到想要的shard上。

Range分区会导致数据不均匀,会否定shard带来的好处,会导致大量数据堆积在同一个shard上,弱化了shard的优势。

Hash分区确保了数据的均匀分布,但是对于区间查询就不可用对一些shard进行炒作,会对所有shard产生影响。

9.1.4 维护数据均衡发布

新增的数据或者新增的服务会导致数据发布不均衡。有一些chunk会包含比其他chunk大的多的数据,或者比其他chunk的数据更加重要。

9.1.4.1 分离(Splitting)

Splitting是一个后台进程,不让chunk变得太大,当chunk超过阀值是就会splits,split会影响元数据,split不会迁移也不会影响shard

9.1.4.2均衡(Balancing)

均衡器也是后台进程用来管理chunk迁移。

当发布数据不均衡的时候,均衡器会从多的shard迁移到小的shard.

1.chunk迁移的时候,目标shard会获取chunk上的所有文档。

2.然后目标shard获取在迁移过程中所有的修改

3.最后shard修改config中相应的location

4.然后删除源中的chunk。但是要迁移大于1chunk的时候,不会先删除,而是进入下一个chunk的迁移。

9.1.4.3 增加和删除Shard

增加和删除shard,都要迁移chunk

9.2 Sharding 概述

9.2.1 Shard集群组件

Shard集群有一下几个组件:

Shard:一个shard是一个mongodb实例,保存了collection数据的一个子集,Shard是单实例,也可以是复制集。

Config Server:每个config server是一个mongod实例,保存了元数据。

Routing Instances:路由是mongos实例,路由从应用程序到shard的读写。应用程序不能直接路由到shard

9.2.1.1 Shards

Shard可以是复制集也可以是一个实例,保存了shard集群的部分数据。通常shard是一个复制集,复制集为每个shard提供了冗余和可用性。

Primary Shard

每个数据库都有一个primary shard用来保存非shard collection

 

可以使用movePrimary命令来修改shard primary 数据库。当部署新的shard集群时,第一个shard会变成primary

Shard状态

使用sh.status()来查看shard状态。

9.2.1.2 Config服务

Config服务比较特殊,保存了shard集群内的所有的元数据。Config服务之间使用二阶段提交的方式来保证一致性和可靠性。Config服务不能使用复制集,所有config服务必须是可用的,来保证元数据的修改。

一般生产环境需要3config服务。当只有一个config 服务,出现单点故障后,config数据被恢复之前是不能访问集群的。

Config数据库

Config服务把元数据存放在config数据库中,mongos会缓存这些数据,来路由数据库操作。

Config服务的读写

只有在一下情况下会写config 服务:

1.在已存在的chunk上创建split

2.shard之前迁移chunk

再有在一下情况下会读config服务:

1.mongos第一次启动

2.迁移chunk后,mongos更新自己的cache

Config服务可用性

当有3config 服务其中1个或2个不可用的时候,集群的元数据变为只读,可以读数据,但是不能迁移chunk或者创建split

如果3config服务都不可用,如果不重启mongos那么任然可以使用集群,如果在config服务可用之前mongos重启了,mongos就不能再路由。

当没有元数据的时候集群变得不可操作,所以保持一个可用的完好的config十分重要。备份起到一个很关键作用。Config服务的数据和整个集群比很小,负荷也少,并且config服务并不要求一直可用来支持shard集群。

shard集群使用的config服务修改了名字或者地址,需要重启每一个mongodmongos,为了避免这种情况,可以使用CNAME来唯一标示衣蛾ocnfig服务。

 

9.2.2 Shard集群体系结构

介绍:shard集群要求,生产环境shard集群结构体系,shard集群测试环境的结构体系。

9.2.2.1 Shard集群要求

Shard是很给力的功能,但shard集群有很多设备的要求,增加了整体部署的复杂性。

对于某些情况来说shard是唯一的解决方法:

1.数据集超过了单个实例处理的能力

2.数据集需要的内存超过了单个实例可以提供的内存

3.大量写的需求,使用其他方法无法解决。

如果没有以上的情况,使用shard只会影响整体的复杂性。

Shard的部署比较花时间,如果系统已经到达了处理能力的边界,再部署shard肯定会影响应用程序的使用。

Shard的部署应该在设计数据结构的时候就应该考虑。

数据量需求

集群会管理大量的数据,数据以chunk为单位进行管理,chunk的大小默认是64MB,当shard之间chunk不均衡的时候(超过了阀值),均衡器会在shard之间迁移chunk知道均衡为止。对于小的collection来说shard是不合算的,光增加了复杂性,除非有写入性能的要求。Chunk默认大小64MB,是可以配置的

9.2.2.2生产环境集群结构

在生产环境下,要保证数据冗余和系统高可用。

组件

Config Server:3Config Server,每个config server有独立的设备,一个shard独占使用config。也就是说config 不能被shard集群共享。

Shards:2个以上的shard,这些shard要求是复制集

Query Rounters(mongos):一个或多个mongosmongos用来路由,一般是每个应用程序服务都有一个mongos实例。

当然,可以在mongos和应用程序之间使用代理和负载均衡,这种情况下使用client affinity来配置负载均衡,这样同一个链接可以一直使用同一个mongos

9.2.2.3测试环境的体系结构

测试环境下:1config server1个以上shard,一个mongos实例。

9.2.3 Shard集群特性

介绍:shard keyshard集群高可用性,shard集群路由

9.2.3.1 Shard Key

Shard key确定了collection的数据分布,shard key是索引字段,或者是组合索引字段。

Mongodb使用shard key来切分collection,每个区间或者chunk,不能重叠。然后mongodb分发这些chunks

Hash过的Shard key

也就是说shard key 可以是一个hash值。

选择字段的时候最好,字段有很高的选择性(相同值数量很少)Hash key在单调递增的字段上也很不错比如objectid或者时间戳。

如果在一个空的collection上使用hash作为shard keymongodb会自动创建和迁移chunk,所以每个shard会有2chunk,当然这个可以通过shardCollection命令中的numInitChunks参数来控制,也可以通过split命令手动创建chunk

Shard key对集群的影响

Shard key通过确定数据的分区和mongos对集群的有效操作来影响性能。

写能力扩展shard key会增加写入的性能,以下objectid为例。

Mongodb为每个文档创建一个objectid,但是有个问题是,是单调增长的,所有的插入都会在一个chunk上一个shard上,那么这个shard写入能力就是整个集群的写入能力。

只有当单调的增加为shard key的很少有插入,这样对性能的影响比较少。

通常使用shard key需要一点随机性。可以让集群扩展写能力。但同时这样的shard key不能提供查询隔离,这个也是shard key重要特性之一。

查询mongos提供了应用程序到shard集群的接口,mongos接受应用程序的请求,使用config server的元数据进行路由,路由到有相应数据的mongod。当mongos路由所有查询操作时,shard key会对查询有很大的影响。

查询隔离:在shard环境中,最快的查询是通过shard key 和元数据被路由到一个shard上的查询。对不包含shard key 过滤的查询会被路由到所有的shard会比较慢。若shard key是组合的,查询对shard key 前缀进行过滤,那么可以被路由到某些shard

Shard key的选择:

1.查询中最常用到的字段

2.哪些操作对性能有很高的依赖

如果一个字段选择度很差,那么就再加个字段提高选择度。

排序:在shard环境下,mongos执行合并排序法来排序从shard中出来的结果

9.2.3.2 Shard集群高可用性

在生产环境下,不能产生单点故障

应用程序或者mongos不可用

如果每个应用程序服务都有自己的mongos,当不可用时,其他的应用可以使用自己的mongosMongos自己不保存数据,重启后不会有数据丢失。

一个shard不可用

Shard级别,复制集提供了可用性,如果primary变得不可用,复制集就会投票生成另一个primary。如果是secondary不可用不影响使用。如果系统变得不可恢复,那么增加新的成员来弥补冗余。

复制集所有成员不可用

如果整个复制集不可用,shard内的数据也变得不可用,但是其他shard的数据还是可用的。就有可能读写到其他成员。所有要能够处理这部分数据,调查清楚问题并恢复。

一个以上Config 数据库不可用

如果有3个不同的config数据,config 数据库之间是使用二阶段提交的。整个集群还是可用的,但是chunk迁移,chunk分离。如果所有config不可用,那么整个集群就不可用。

重命名Config服务和集群可用性

如果连接到config的名字和地址被修改,必须重启所有的mongodmongos。使用CNAMEDNS)可以完成换服务器,但是可以不修改连接字符串。

Shard key和集群可用性

选择Shard Key要考虑:

1.保证mongod可以均匀的分布数据

2.可以扩展写能力

3.保证mongos在大多数查询上可以查询隔离,也就是路由到指定的mongod

跟多:

1.每个shard应该是一个复制集

2.如果可以隔离大多数操作,shard不可用,只会影响部分数据。

3.如果每个操作都要发布到整个集群,当一个shard不可用会导致整个集群不可用。

9.2.3.3 Shard集群查询路由

Shard对应用程序来说是透明的。Mongos缓存了config的数据,进行路由工作。一般的做法mongos都是在应用程序服务器上,也可以在shard上或者其他专用设备上。

路由进程

Mongos使用一下过程路由到结果:

决定哪些Shard接收查询

1.确定哪些shard必须接收查询

2.在这些shard上创建游标。

如果查询中使用shard key或者shard key前缀过滤可以只查询shard的子集。

Mongos如何处理查询Modifiers

如果查询的结果不要求是排序的,mongos会打开一个游标然后循环shard上来的结果。如果指定了排序,那么把排序给shardmongosshard基础上执行合并排序。如果有limit会把limit传给shard,再在结果上limit。若有skip那么不会传,如果有limitskip那么会传limit,传给shardlimit的个数为skip个数加上limit的个数。

诊断到Mongos的连接

如果连接到的是mongos,使用ismaster命令会返回:

{

"ismaster":true,

"msg":"isdbgrid",

"maxBsonObjectSize":16777216,

"ok":1

}

其中msgisdbgrid,如果连接到的是mongod不会包含isdbgrid

广播操作和目标操作

shard集群中操作有2:

1.会广播到所有shard的操作,如remove

2.以一部分shard为目标的操作,如insert

Shard和非Shard数据

Shard是在collection级别的,可以在多个数据库的多个collectionshard。不管集群的结构,所有的查询和操作都使用mongos路由到数据中心。

9.2.4 Shard机制

介绍,shard collection均衡,chunk迁移,chunk splitShard key所有,shard集群元数据。

9.2.4.1 Shard Collection均衡

Mongodb使用均衡器来平衡shard之间的数据。当一个shard的数据过多,均衡器会启动分发给其他shard

集群均衡器

均衡器是用来均衡shard之间的数据量,默认均衡器是开启的。

任何mongos实例都可以启动均衡流程。当均衡器被激活,mongos要修改config数据库中的lock collection,获得锁。

均衡器一旦启动,只有当chunk均衡的时候才会停止。

Chunk迁移会导致负荷上升,影响应用的性能。有2个方法减少影响:

1.一次只迁移一个chunk

2.或者只有当最大chunks个数和最小chunks个数只差超过一个阀值。

当然也可以临时关闭均衡器

迁移阀值

Number of Chunks

Migration Threshold

Fewer than 20

2

21-80

4

Greater than 80

8

一旦均衡器启动只有当2shardchunk差为2或者迁移失败才会停止。

Shard 大小

默认mongodb会试图占满所有的可用空间,为了保证还有性能和空间继续扩展,要监视磁盘可用空间和磁盘性能。

当添加shard的时候可以设置shard最大大小。可以方式shard往里面移动数据。

9.2.4.2 ShardChunk迁移

Chunk迁移

Chunk迁移可以:1.手动迁移,2.自动迁移(通过均衡器)

所有的迁移都是一下过程:

1.均衡器发送moveChunk命令道源shard

2.Shard使用内部的moveChunk命令。源Shard负责处理写入

3.目标Shard开始复制数据

4.接受到之后一个文档之后,目标sahrd开始同步,保证被修改的文档可以被同步过来

5.当都被同步完成,目标shard连接到config数据库,修改集群元数据

6.当修改完元数据,并没有游标,删除chunk上的文档。

若要进行另外一个chunk迁移,不用等待当前chunk删除完成,直接进行。

Chunk迁移队列

为了让迁移速度更快,均衡器并不会等待当前迁移删除chunk,就启动下一个迁移。

Chunk迁移写注意

删除chunk的时候等待发布到secondary,会导致迁移速度下降,但是保证了大量chunk迁移的时候集群的可用性。具体看chunk迁移修改复制集行为

9.2.4.3 Shard集群下Chunk的分离

Chunk的大小超过了指定的chunk大小,mongos会把这个chunk分成2

Chunk大小

默认Chunk的大小为64MB,也可以通过配置增加减少chunk的大小。

1.小的chunk大小,会让数据更加平均,但是迁移量变大,成本增加。

2.大的chunk会让迁移变少,但是数据不均衡。

限制

Chunk大小的修改也会影响chunk分离。

1.自动分离只会发生在插入和修改

2.分离不能被undoen,如果增加了chunk的大小,chunk只有在insertupdate的时候增长才会变成新的大小。

9.2.4.4 Shard Key索引

所有的shard collection都要有个索引用于shard key,如果没有文档没有索引,shardCollection命令会在shard key上创建索引。如果已经有文档了,那么要在shardCollection之前创建好索引。

Shard key不能是multikey索引。

如果shard collectionzipcodeshard key可以使用如下方法来替换索引:

1.创建一个索引zipcode,username

2.删除zipcode这个索引

删除了最后一个可用索引之后,可以重新在shard key创建索引来恢复。

9.2.4.5Shard集群元数据

Config服务保存了集群的元数据,元数据反映了状态和shard数据集和系统的组合。mongos实例缓存了这些数据并使用它来路由读写操作。config数据库包含了以下collection

·changelog

·chunks

·collections

·databases

·lockpings

·locks

·mongos

·settings

·shards

·version

9.3 Shard集群教程

主要介绍如何管理shard集群

9.3.1 Shard集群部署教程

部署shard集群,考虑shard key,使用hash shard key分片collectionshard集群验证,添加shard到集群,为生产环境部署3config server,把复制集转化为shard集群,把shard转化为复制集。

9.3.1.1部署shard集群

启动Config服务

config服务是保存了集群元数据的mongod,启动的时候标记configsvr,每个config保存了一份完整的集群元数据。

生产环境下最好在不同的服务器上部署3config服务。

1.config服务创建数据文件夹

mkdir /data/configdb

2.启动mongod服务

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

默认端口是27019,当然可以通过--port来指定端口。

启动mongos实例

mongos是很轻量的不要求数据文件夹。默认端口是27017。启动mongos的时候需要指定config服务,可以在命令行也可以在配置文件下。最好给每个config服务一个DNS,这样换服务器的时候就不会有下线时间。

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

每个mongos启动的时候必须要有相同的configdb配置字符串。

增加Shard到集群中

shard可以是复制集也可以是单个实例,对于生产环境应该要求都是复制集。

1.使用mongo连接到mongos

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

2.使用sh.addShard添加shard到集群

添加一个复制集,添加一个成员就可以了,以前的版本要添加所有的成员。

sh.addShard("rs1/mongodb0.example.net:27017")

添加一个单实例shard

sh.addShard("mongodb0.example.net:27017")

启动数据库中的Shard

在真正shard collection之前要先启用数据库的shard

1.连接到mongos

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

2.使用sh.enableShard()命令对数据库启用shard

sh.enableSharding("<database>")

也可以使用命令:db.runCommand({enableSharding:<database>})

启动CollectionShard

1.确定shard key

2.如果collection已经有数据库的要先在shard key上创建索引使用ensureIndex(),如果是空的,Mongodb会通过sh.shardCollection创建。

3.使用sh.shardCollection() shard一个collection

sh.shardCollection("<database>.<collection>",shard-key-pattern)

shard-key-pattern表示shard key

如:

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"})

9.3.1.2考虑Shard Key

选择Shard Key

以下是帮助你找到合适的shard key的策略:

1.在应用程序层先计算好理想的shard key,然后保存到文档中

2.使用组合shard key使用,前缀来提高写能力和读隔离

3.在这些情况下,不好的shard key 并没有很大的影响:有限的写入,预期的数据大小,应用程序查询方式。

4.使用hash shard key,选一个选择度高的然后创建hahs索引。然后使用这个hash索引为shard key的值。

考虑Shard Key的选择性shard key的选择对性能,选择度,集群的功能影响重大。

创建一个易切分(divisible)的shard key

一个易切分的shard keymongodb分发数据比较简单,如果只有有限的几个值会让chunk无法分割。

创建一个高随机的shard key

一个高随机的shard key不会让任何一个shard变成瓶颈,并且可以在集群中发布写操作(不会只写入到一个shard)。

对于一个shard创建一个shard key

一个shard一个shard key可以让mongos直接从一个shard上返回结果,但是shard key必须最为主要的过滤条件。使用高随机的shard key 很难再指定的shard 上操作。

使用组合shard key

当存在在collection中的字段都不是最优的key,那么选择多个字段作为组合shard key会更加的理想。

基数(cardinality 选择性类似)

基数决定了这个系统中可以分为几个chunks

1.如果用state作为shard key,因为state少会造成集群不均衡有以下影响:

         a.不能分离chunks因为这个chunk都是同一个shard key,迁移这些chunk变得无比困难。很难让集群均衡。

         b.如果固定了chunks的个数,那么就不能超过这个个数了。

2.zipcode字段作为shard key

         这个字段选择度高但是也有可能照成un-splittable的情况,有些用户很多,有些却很少。

3.考虑手机号码作为shard key

         手机号码是高基数(和选择度一样)的,所有的用户都有自己的手机号码并且是唯一的。

高基数可以保证数据均衡,但是不能保证查询隔离和合适的写扩展。

9.3.1.3使用Hash Shard Key

Hash Shard Key是使用Hash索引的字段

Shard Collection

使用shard keyshard collection

sh.shardCollection( "records.active", { a:"hashed" } )

使用ahash值作为shard key

指定初始化Chunks

如果使用hash shard keyshard空的collectionmongodb会自动创建和迁移空的chunks。每个shard2chunks。可以使用shardCollectionnumInitialChunks来控制初始化collectionchunk个数。

Mongodb hash索引会截断float小数点后面的值,再计算。

9.3.1.4 Shard集群的认证

使用—keyfile来控制集群内组件的互通,keyfile都一样,内容可以随意

过程

1.创建key file保存认证信息

2.通过以下方式启用验证:

         a.在配置文件中:keyFile = /srv/mongodb/keyfile

         b.在命令行上配置—keyfile

3.添加第一个管理员,创建一个管理员

9.3.1.5添加Shard到集群

shard增加到集群的时候要保证,集群有足够的能力来迁移数据。

添加一个shard 到集群

1.使用mongo连接到mongos

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

2.使用sh.addShard增加shard

添加一个复制集,添加一个成员就可以了,以前的版本要添加所有的成员。

sh.addShard("rs1/mongodb0.example.net:27017")

添加一个单实例shard

sh.addShard("mongodb0.example.net:27017")

9.3.1.6为生产环境部署3Config服务

这个过程是把只有单个config的测试环境转变为3config服务的生产环境。

1.关闭所有mongodb进程

2.复制dbpath下的所有文件到其他config服务

rsync -az /data/configdb mongo-config1.example.net:/data/configdb

rsync -az /data/configdb mongo-config2.example.net:/data/configdb

3.启动所有3config server

mongod --configsvr

4.重启所有的mongodmongos

9.3.1.7把复制集转化为shard集群

概述

这个过程是把3成员的复制集转为2shard的集群,每个shard3成员的复制集。

1.创建选择一个3成员的复制集,插入一些数据到collection

2.启动config数据库,并且创建一个单shard的集群

3.创建第二个复制集

4.把第二个复制集添加到这个集群上

5.在需要shardcollection进行shard

过程

使用测试数据部署复制集:使用下面的顺序来部署复制集

1.为复制集创建文件夹。

mkdir -p /data/example/firstset1 /data/example/firstset2 /data/example/firstset3

2.启动3mongod实例

mongod --dbpath /data/example/firstset1 --port 10001 --replSet firstset --oplogSize 700 --rest

mongod --dbpath /data/example/firstset2 --port 10002 --replSet firstset --oplogSize 700 --rest

mongod --dbpath /data/example/firstset3 --port 10003 --replSet firstset --oplogSize 700 --rest

3.使用mongo打开一个shell

4.通过以下命令来初始化复制集

db.runCommand({"replSetInitiate":

                    {"_id":"firstset", "members": [{"_id":1, "host":"localhost:10001"},

                                                      {"_id":2, "host":"localhost:10002"},

                                                      {"_id":3, "host":"localhost:10003"}

             ]}})

{

"info":"Config now saved locally.  Should come online in about a minute.",

"ok":1

}

5.使用一下代码插入测试数据

use test

switched to db test

people = ["Marc", "Bill", "George", "Eliot", "Matt", "Trey", "Tracy", "Greg", "Steve", "Kristina", "Katie", "Jeff"];

for(var i=0; i<1000000; i++){

                             name = people[Math.floor(Math.random()*people.length)];

                             user_id = i;

boolean= [true, false][Math.floor(Math.random()*2)];

                             added_at =newDate();

                             number =Math.floor(Math.random()*10001);

                             db.test_collection.save({"name":name, "user_id":user_id, "boolean":boolean, "added_at":added_at, "number":number });

                            }

部署Shard基础设施:这个过程创建了3config数据库

1.config服务创建文件夹

mkdir -p /data/example/config1 /data/example/config2 /data/example/config3

2.启动config数据库

mongod --configsvr --dbpath /data/example/config1 --port 20001

mongod --configsvr --dbpath /data/example/config2 --port 20002

mongod --configsvr --dbpath /data/example/config3 --port 20003

3.启动mongos实例

mongos --configdb localhost:20001,localhost:20002,localhost:20003 --port 27017 --chunkSize 1

--chunkSize表示chunk的大小这里是1MB

4.添加第一个shard

         a.连接到mongos

         mongo localhost:27017/admin

         b.增加使用addShard增加sahrd

         db.runCommand( { addShard :"firstset/localhost:10001,localhost:10002,localhost:10003" } )

         c.返回一下信息说明添加成功

         { "shardAdded":"firstset", "ok":1 }

部署第二个复制集:下面的过程部署第二个复制集

1.创建复制集文件夹

  • /data/example/secondset1
  • /data/example/secondset2
  • /data/example/secondset3

2.启动3mongod实例

mongod --dbpath /data/example/secondset1 --port 10004 --replSet secondset --oplogSize 700 --rest

mongod --dbpath /data/example/secondset2 --port 10005 --replSet secondset --oplogSize 700 --rest

mongod --dbpath /data/example/secondset3 --port 10006 --replSet secondset --oplogSize 700 --rest

3.连接到mongos

mongo localhost:10004/admin

4.初始化第二个复制集

db.runCommand({"replSetInitiate":

                    {"_id":"secondset",

"members": [{"_id":1, "host":"localhost:10004"},

                                  {"_id":2, "host":"localhost:10005"},

                                  {"_id":3, "host":"localhost:10006"}

             ]}})

 

{

"info":"Config now saved locally.  Should come online in about a minute.",

"ok":1

}

5.把复制集增加到集群

use admin

db.runCommand( { addShard :"secondset/localhost:10004,localhost:10005,localhost:10006" } )

是不是只写一个成员就可以了

6.验证shard成员,使用listShards命令

db.runCommand({listShards:1})

{

"shards": [

              {

"_id":"firstset",

"host":"firstset/localhost:10001,localhost:10003,localhost:10002"

              },

              {

"_id":"secondset",

"host":"secondset/localhost:10004,localhost:10006,localhost:10005"

              }

      ],

"ok":1

}

启动Shardmongodb必须要再数据库和collection级别启动shard

在数据库级别启动Shard:使用enableSharding命令启动数据库

db.runCommand( { enableSharding :"test" } )

{ "ok":1 }

在索引上创建Shard KeyMongodb使用shard key来发发布数据到shard,一旦决定之后你不能修改shard key。好的shard key

1.可以均衡的分发数据

2.经常被同时访问的文档会被放在连续的chunk

3.在活动的shard中有效的分发

Shard key一般的选择是复合索引,hash或者主键。Shard key的选择还是和数据,应用程序结构和使用方式有关。

Shard Collection

use admin

db.runCommand( { shardCollection :"test.test_collection", key : {"number":1} })

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

之后均衡器会均衡chunk,可以在test下的db.stats()或者db.printShardIngStatus()查看是否在同步。

9.3.1.8shard集群转化为复制集

把一个有复制集的集群转为复制集

这个例子是,集群只有一个shard复制集,用以下方法把shard转为复制集

1.配置应用程序连接到primary成员

2.如果启动的时候有shardsrv选项,那么删除这个选项。

把集群转为复制集

1.创建一个新的复制集,保证这个复制集的性能能够达到要求。

2.停止所有的写入。通过重新配置应用程序或者停止所有mongos

3.使用mongodumpmongorestore备份恢复数据到新的复制集

4.配置应用程序连接到新的复制集

9.3.2 Shard集群维护教程

查看集群配置,使用相同的名字迁移config服务,使用不同的名字迁移config服务,替换ocnfig服务,迁移shard到不同的硬件,备份元数据,配置均衡器,管理均衡器,删除shard

9.3.2.1查看集群配置

查看shard可用的数据库

通过在config数据库对databases collection的查询

use config

db.databases.find( { "partitioned":true } )

查看所有的shard

使用listShards命令查看

use admin

db.runCommand( { listShards :1 } )

查看集群的细节

使用db.printShardingStatus,sh.status查看集群的细节

Sh.status返回一下:

Sharding version显示shard元数据版本

Shards显示了shard的列表

Database显示了集群中的所有数据库

Chunks信息显示了每个shard有几个chunk

9.3.2.2使用相同的hostname迁移config

config迁移到同名的系统。如果要迁移所有的config那么每个都执行一下过程:

1.关闭这个config server,会影响config数据,只读

2.修改dns指向新的系统

3.复制老的config的数据到新的系统上

rsync -az /data/configdb/ mongodb.config2.example.net:/data/configdb

4.然后以config服务启动mongod

mongod --configsvr

当第三个config启动集群的元数据有可以被写入(可以迁移chunksplit chunk

9.3.2.3在不同HostName之前迁移config

这个过程迁移config服务到一个新的不同名的服务器,这样会修改config的主机名,还会导致下线时间和集群内的所有进程重启。

如果要迁移所有config,依次按一下过程执行:

1.关闭均衡器

2.关闭config服务,会导致config数据只读

3.复制老的config的数据到新的系统上

rsync -az /data/configdb/ mongodb.config2.example.net:/data/configdb

4.然后以config服务启动mongod

mongod --configsvr

5.关闭所有mongodb进程,包括:shardmongod或者复制集,提供config服务的mongodmongos实例。

6.重启所有提供shard服务器的mongod

7.更新mongosconfigdb设置

8.重启mongos

9.重启均衡器

9.3.2.4替换一个Config服务

这个过程是替换不可用的config服务。这个过程假设替换过程中,hostname不就被修改。

1.关闭均衡器(是否可以不关闭,是为了让元数据不可写,但是如果config已经出现不可用,没有必要。

2.提供一个新的系统和之前的设备有一样的hostname

3.关闭其中一个config服务,复制数据到新的设备上

rsync -az /data/configdb/ mongodb.config2.example.net:/data/configdb

4.启动之前是好的config服务

5.启动新的config服务

mongod --configsvr

6.启动均衡器

9.3.2.5迁移集群到不同的硬件环境

这个过程是启动shard集群到一个新的环境下。没有宕机时间,迁移状况下可读写。

如果集群下有单节点shard那么先把这个mongod转变为复制集可以让你的集群一直在可用状态下。

关闭均衡器

关闭均衡器来停止chunk迁移,在整个过程中不要有元数据写入,若均衡器已经启动了迁移,那么先等待均衡器迁移完,在执行这个过程。sh.stopBalancer()来关闭均衡器。然后可以使用sh.getBalancerStatue()来查看均衡器状态。

迁移config服务

mongosconfigdb配置的字符串,从最后一个开始迁移。不要重命名config服务。

1.关闭config服务,元数据变成只读

2.修改DNS指向新的设备

3.复制数据到新的设备上

rsync -az /data/configdb/ mongodb.config2.example.net:/data/configdb

4.然后以config服务启动mongod

mongod --configsvr

重启mongos实例

如果configdb修改是迁移的一部分,那么就需要在修改configdb之前关闭mongos。避免出现configdb字符串不一样的冲突。

如果configdb保持不变,只要顺序的迁移就可以了:

1.关闭mongos实例,使用shutdown命令,如果configdb字符串要修改,要关闭所有mongos实例。

2.如果config服务hostname修改,更新所有mongosconfigdb字符串。

3.重启mongos实例确保已经更新了configdb

迁移Shard

使用一下过程迁移shard

迁移一个复制集:为了迁移整个集群,就需要迁移shard,要迁移shard,就要迁移secondary

如果是2vote的集群那么要加一个仲裁,迁移结束后可以把仲裁删掉。

迁移复制集的一个成员

1.关闭mongod,确保感觉关闭,可以使用shutdown命令

2.启动数据文件夹到新的设备上

3.在新的设备上重启mongod

4.连接到集群的当前primary

5.如果hostname被修改,使用rs.reconfig()重新配置。

cfg=rs.conf()

cfg.members[2].host="pocatello.example.net:27017"

rs.reconfig(cfg)

6.确认复制集配置,rs.config()

7.等待成员恢复,使用rs.status()查看状态

迁移Shard复制集中的Primary:迁移过程中,当执行选举的时候才会让复制集不可用,不能执行读写。但是选举的过程很快。

1.stepDown primarysecondary上来当primary

2.查看复制集进程,看看是否成功变成secondary,变成secondary之后在执行迁移secondary的步骤。

迁移单实例Shard:单实例shard迁移的时候,先转化为复制集然后再迁移。

重新启动均衡器

连接到mongos实例,然后执行sh.setBalancerState(true)

9.3.2.6备份集群元数据

1.关闭均衡器

2.关闭其中一个config

3.备份整个数据文件夹

4.重新启动config

5.启动均衡器

9.3.2.7配置均衡器进程行为

均衡器运行在其中一个mongos上,保证chunks在集群中的均衡分布。默认的均衡器的配置已经足够使用了。管理员也有可以根据应用来重新配置均衡器。

配置均衡器调度窗口

均衡器调度窗口,是均衡器只能在这个窗口时间内调度。

具体看均衡器管理中的均衡器调度窗口删除均衡器调度窗口

配置默认chunk大小

默认chunk的大小为64MB,当然可以修改chunk的大小,通过修改config数据库中的settings collection。也可以在mongos启动是,指定参数--chunkSize来指定chunk的大小。

修改指定Shard的最大存储大小

最大存储大小,指定后,如果mapped大小超过了最大存储大小,均衡器就不会再移入数据这个mapped大小是值所有被映射的数据库文件的大小。maxsize被保存在config数据库中的shards collection下。

默认maxsize可以无限大,撑满所有可用空间为止。这个maxsize可以在添加shard的时候指定也可以手动修改:

1.通过addShard指定,单位MB

db.runCommand( { addshard : "example.net:34008", maxSize : 125 } )

2.修改已存在shardmaxsize

use config

db.shards.update( { _id : "shard0000" }, { $set : { maxSize : 250 } } )

chunk迁移修改复制集行为

2.2.1之后_secondaryThrottle变成moveChunk命令的一个参数。_secondaryThrottle可以让均衡器在迁移是等待secondary完成。

2.4之后,_secondaryThrottle默认启动。

当启动之后,secondary会要求写注意为{w:2}来保证修改至少被写入一个secondary

可以通过以下命令来设置_secondaryThrottle

useconfig

db.settings.update(

   {"_id":"balancer"},

   {$set:{"_secondaryThrottle":true}},

   {upsert:true}

)

9.3.2.8管理均衡器

检查均衡器状态

使用sh.getBalancerState()查看均衡器状态

检查均衡器锁(查看均衡器是否活动)

为了查看均衡器进程是否活动可以使用以下过程:

1.连接到mongos

2.切换到config

3.查看config中的locks collection查看均衡器是否活动

db.locks.find({_id:"balancer"}).pretty()

输出:

{   "_id":"balancer",

"process":"mongos0.example.net:1292810611:1804289383",

  "state":2,

     "ts":ObjectId("4d0f872630c42d1978be8a2e"),

   "when":"Mon Dec 20 2010 11:41:10 GMT-0500 (EST)",

    "who":"mongos0.example.net:1292810611:1804289383:Balancer:846930886",

    "why":"doing balance round"}

1.process可以看出均衡器进程运行在mongos0.example.net

2.state状态为2 说明在活动中,早期的版本为1

均衡器调度窗口

当数据增长很缓慢,并且迁移会影响性能的时候,可以使用调度窗口来限制均衡器的调度。

1.连接到mongos

2.切换到config数据库

3.使用一下命令来修改调度器窗口

db.settings.update({_id:"balancer"},{$set:{activeWindow:{start:"<start-time>",stop:"<stop-time>"}}},true)

如:

db.settings.update({_id:"balancer"},{$set:{activeWindow:{start:"23:00",stop:"6:00"}}},true)

删除均衡器调度窗口

使用一下命令来删除调度窗口

useconfig

db.settings.update({_id:"balancer"},{$unset:{activeWindow:true}})

关闭均衡器

默认均衡器只有在需要均衡数据的时候运行。也可以使用一下过程关闭均衡器:

1.连接到mongos

2.使用命令sh.setBalancerState(false)来关闭均衡器

3.通过sh.getBalancerState()来获取均衡器状态

可以用以下代码验证关闭后不再有迁移:

useconfig

while(sh.isBalancerRunning()){

          print("waiting...");

          sleep(1000);

}

驱动下,关闭均衡器只能修改settings collection

db.settings.update({_id:"balancer"},{$set:{stopped:true}},true)

启动均衡器

1.使用mongo连接到mongos

2.使用以下任意一种语句来启用:

sh.setBalancerState(true)

db.settings.update({_id:"balancer"},{$set:{stopped:false}},true)

在备份的时候关闭均衡器

mongodb在迁移时备份会导致数据不一致,所以要在备份时关闭均衡器。可选方法:

1.设置均衡器调度窗口,在窗口外备份

2.手动关闭均衡器

如果关闭均衡器的时候有迁移在处理,那么会先等待迁移完成,然后清理掉之后要迁移的。

要在备份前确认是否有均衡器在运行。

!sh.getBalancerState()&&!sh.isBalancerRunning()

9.3.2.9删除Shard集群中的Shard

为了删除shard,必须确认shard中的数据已经被迁移出去了。不要使用一下过程来迁移整个shard集群到一个新的环境。

确保均衡器是启动的

使用sh.getBalancerState()来查看均衡器是否启动。

确定要删除shardhostname

1.使用listShards查看shard

db.adminCommand( { listShards:1 } )

2.使用sh.status()或者db.printShardingStatus()查看shard

shard中删除chunk

使用removeShard命令来抽取shard中的chunk到其他shard

useadmin

db.runCommand({removeShard:"mongodb0"})

输出

{

    "msg":"draining started successfully",

    "state":"started",

    "shard":"mongodb0",

    "ok":1

}

检查迁移状态

查看迁移状态可以使用一下命令

useadmin

db.runCommand({removeShard:"mongodb0"})

输出

{

     "msg":"draining ongoing",

    "state":"ongoing",

    "remaining":{

        "chunks":42,

        "dbs":1

    },

    "ok":1

}

其中remaining文档显示了剩下要迁移的chunksdbs表示这个数据库中primary的数据库个数。

移动非shard数据

shard环境下,只有primary数据库有非shardcollection

1.使用一下命令查看,删除的shard是不是primary

·  sh.status()

·  db.printShardingStatus()

输出中,databases字段列了所有数据库和它的primary,以下结果说明products数据库的primarymongodb0上:

{  "_id":"products",  "partitioned":true,  "primary":"mongodb0"}

2.使用movePrimary命令移动primary

db.runCommand({movePrimary:"products",to:"mongodb1"})

这个命令只有当全部处理完之后才会返回

完成迁移

为了清理所有的元数据和完成迁移,再次使用removeShard命令

useadmin

db.runCommand({removeShard:"mongodb0"})

当完成的时候会返回以下结果:

{

    "msg":"removeshard completed successfully",

    "state":"completed",

    "shard":"mongodb0",

    "ok":1

}

只有完成到这步的时候,你才能完全的关闭这个shard的进程。

9.3.3 Shard集群的数据管理

创建chunksplit chunk,迁移chunk,修改chunk大小,Tag意向Sharding,管理Shard Tag

,强制唯一键,Shard GridFS数据存储。

9.3.3.1创建Chunks

很多情况下shard集群会自动创建和发布chunk,不需要用户参与,但是有些场景下,Mongodb不能创建猪狗的chunk或者发布数据不够快,如:

1.shard一个以前只存储在primarycollection

2.想要提取大量数据到集群中,这种提取会导致不均衡,特别是单向增长或者单向递减的数据,会插入到单个chunk中。

这些操作时资源密集型有以下几个理由:

1.chunk迁移是把chunk里面的数据从这个shard复制到另外一个shard

2.mongodb一次只迁移一个chunk

3.mongodb只会在插入操作后才split

只能在空的collectionsplit,如果在已经有数据的collection会自动split,如果手动split,会导致无法估计chunk个数和大小,会影响数据均衡的行为。

例,可以使用一下代码来创建chunk

for ( var x=97; x<97+26; x++ ){

  for( var y=97; y<97+26; y+=6 ) {

    var prefix = String.fromCharCode(x) + String.fromCharCode(y);

    db.runCommand( { split : "myapp.users" , middle : { email : prefix } } );

  }

}

9.3.3.2 Split Chunk

如果chunk大小草果chunk sizemongodb会自动的split这个chunk。但是还是会有手动split chunk出现:

1.有大量的数据但是chunk比较少

2.如果想要导入大量的数据,这些数据起初是在单个chunkshard 上的。

mongos认为迁移对未来插入性能有好处,均衡器可能会迁移splitchunk到一个新的shard。均衡器不会中断手动的split,也不会中断自动的split

使用sh.status确定当前chunks

使用split命令来split chunk,要不是middle,要不是find也可以使用sh.splitFind()sh.splitAt()

在有某个值的chunk进行平均的split

sh.splitFind( "records.people", { "zipcode":"63109" } )

对指定位置进行split,新的chunk的边界从指定的值开始。

sh.splitAt( "records.people", { "zipcode":"63109" } )

9.3.3.3迁移Chunk

一般chunk迁移都是自动的,但是以下情况可以考虑自动迁移:

1.split空的collection,然后分发他们

2.如果在均衡窗口内无法迁移chunk

使用moveChunk命令来迁移chunk

db.adminCommand( { moveChunk : "myapp.users",

                   find : {username : "smith"},

                   to : "mongodb-shard3.example.net" } )

把包含shard key smithchunk启动到mongodb-shard3

可以使用如下命令迁移:

var shServer = [ "sh0.example.net", "sh1.example.net", "sh2.example.net", "sh3.example.net", "sh4.example.net" ];

for ( var x=97; x<97+26; x++ ){

  for( var y=97; y<97+26; y+=6 ) {

    var prefix =String.fromCharCode(x) +String.fromCharCode(y);

    db.adminCommand({moveChunk :"myapp.users", find : {email : prefix}, to : shServer[(y-97)/6]})

  }

}

2.2版本后,会有个_secondaryThrottle参数当为true时,mongodb会保证对chunk的迁移分发到secondary

当出现以下错误时是有太多游标打开了这个chunk,要不等待游标关闭,要不干掉游标。

The collection's metadata lock is already taken.

9.3.3.4修改Chunk的大小

如果你注意到,自动迁移超过了硬件的处理能力,就可能想要减少chunk大小。修改chunk大小过程:

1.连接到mongos

2.切换到config数据库

3.使用save命令来保存chunk大小

db.settings.save( { _id:"chunksize", value: <sizeInMB> } )

修改chunk有一下几个限制:

1.自动split会在插入或者修改的时候发生

2.如果设置了低的chunk,那么需要时间来split所有的chunk

3.split是不能undone

4.如果增加了chunk的大小,那么只有通过insert,和updatechunk增长到新的大小。

9.3.3.5 Tag意向Sharding

Mongodb支持通过tag标记一组shard key来指明一个shard或者一组shard。可以通过tag做到以下事情:

1.把数据库隔离到指定的shard

2.保证相关的数据所在的shard 的位置

行为和操作

tag标记了一组shard key。均衡器通过chunkshard key迁移到tag的高值比chunk低值大的shard下。

如果collection中的chunks不均衡,均衡器迁移,均衡器迁移tag区间内的chunk到,关联到这个tagshard中。

配置tag,关联到一个或者多个shard之后,集群可能会花一些时间均衡shard中的数据,取决于当前的数据分布。

跨多个tagchunk

一个chunk包含的shard key可能跨多个tag,为了解决这个问题,均衡器可能会把chunk迁移到比chunkshard key小的tag上。

如:有2tag

1.shard key 100-200tag NYC

2.shard key200-300tag SFO

当有一个chunk要迁移shard key150-220,那么会被迁移到NYC,因为150200比到300近。

9.3.3.6管理Shard Tag

标记Shard

使用sh.addShardTag()tag和指定的shard关联,一个shard可以有多个shard,多个shard也可以有一个tag

sh.addShardTag("shard0000", "NYC")

sh.addShardTag("shard0001", "NYC")

sh.addShardTag("shard0002", "SFO")

sh.addShardTag("shard0002", "NRT")

使用sh.renoveShardTag来删除关联

sh.removeShardTag("shard0002", "NRT")

标记Shard Key

使用sh.addTagRange()shard key分配给tag

1.分配2个数组给NYC

2.分配一个数组给SFO

sh.addTagRange("records.users", { zipcode: "10001" }, { zipcode: "10281" }, "NYC")

sh.addTagRange("records.users", { zipcode: "11201" }, { zipcode: "11240" }, "NYC")

sh.addTagRange("records.users", { zipcode: "94102" }, { zipcode: "94135" }, "SFO")

删除Tag上的Shard key

use config

db.tags.remove({ _id: { ns: "records.users", min: { zipcode: "10001" }}, tag: "NYC" })

查看存在的shard tag

通过sh.status查看被管理到shardtagshardtag被存在config数据库shards collection下,通过查询shards collection查看tag

use config

db.shards.find({ tags: "NYC" })

tagshard key组被保存在configtags collection下,sh.status()也显示了tagshard key

use config

db.tags.find({ tags: "NYC" })

9.3.3.7 shard集群强制唯一键

唯一约束是在collection中每个文档有一个唯一的值。对于shard集群来说,唯一约束不能约束整个shard collection,只能约束本地的collection

如果要保证整个collection的唯一性,有2个选择:

1.使用shard key 可以的唯一性

2.shard collection创建非shardcollection来约束唯一性。

Shard key唯一性约束

过程:可以在shardCollection中指定unique保证唯一性

db.runCommand( { shardCollection : "test.users" , key : { email : 1 } , unique : true } );

限制

1.只能限制一个字段的唯一性

2.可以使用组合的shard key,只能对组合进行唯一约束

很多情况下,最好的shard key是组合的可以允许读隔离和写扩展。

其他字段的唯一约束

若不能创建到shard key,或者需要在多个字段强制唯一性,你就必须创建一个代理collection,这个collection包含了到原始文旦的引用和要唯一的字段。

过程:如果要在email字段保持唯一性

{

  "_id" : ObjectId("...")

  "email" ": "..."

}

_id反应了原始文档,email是要唯一的字段

如果collectionshard

db.runCommand( { shardCollection : "records.proxy" ,

                 key : { email : 1 } ,

                 unique : true } );

如果不需要shard

db.proxy.ensureIndex( { "email" : 1 }, { unique : true } )

在插入数据时的操作:

db = db.getSiblingDB('records');

 

var primary_id = ObjectId();

 

db.proxy.insert({

   "_id" : primary_id

   "email" : "example@example.net"

})

 

// if: the above operation returns successfully,

// then continue:

 

db.information.insert({

   "_id" : primary_id

   "email": "example@example.net"

   // additional information...

})

考虑

1.你的应用程序必须要能够抓取插入报错

2.如果代理collectionshard,只能在要保持唯一性的字段作为shard key唯一

3.在多于1个字段唯一性,你必须为每个字段创建代理collection,如果要再一个collection上创建多个唯一性,那么就不能shard

9.3.3.8 Shard GridFS数据存储

当要shard一个GridFS存储,考虑一下几点:(不知道为啥要对file collection chunk collection进行shard)

File collection
Chunks Collection

9.3.4 Shard集群Troubleshoot

9.3.4.1 Config数据库错误字符串

Mongosconfigdb都要使用同一个字符串,不然会有一下错误:

could not initialize sharding on connection

mongos specified a different config database string

9.3.4.2 因为老的config数据导致游标错误

如果mongos没有及时更新元数据的cache

could not initialize cursor across all shards because : stale config detected

9.3.4.3在移动config服务避免下线

使用DNS名称来减少下线时间,名称一改所有成员都要重启。

9.4 Shard Reference

http://docs.mongodb.org/manual/reference/sharding/

也可以看

http://docs.mongodb.org/manual/reference/

 

posted on 2014-04-15 13:15  Fanr_Zh  阅读(2630)  评论(4编辑  收藏  举报