在MongoDB(版本 3.2.9)中,数据的分发是指将collection的数据拆分成块(chunk),分布到不同的分片(shard)上,数据分发主要有2种方式:基于数据块(chunk)数量的均衡分发和基于片键范围(range)的定向分发。MongoDB内置均衡器(balancer),用于拆分块和移动块,自动实现数据块在不同shard上的均匀分布。balancer只保证每个shard上的chunk数量大致相同,不保证每个shard上的doc数量大致相同。

一,数据按照chunk数量进行均衡分发

均衡分发是MongoDB自动实现的,使数据库架构对Application透明,简化系统的管理,使得向分片集群中增减分片变得容易。均衡分发是由MongoDB内置均衡器(balancer)来实现的,Balancer按照collection的索引字段来进行数据分发,该字段叫做片键(sharded key)。片键一般有三种类型:升序片键,随机片键和基于分组的片键。

块(chunk)是由多个doc组成的一个分组,在某个索引字段(片键)上是连续的,每个chunk的片键是有一定范围的。块的默认大小是64MB。有些chunk会非常大,包含的doc数量非常多,但是,在MongoDB看来,仍然是一个chunk,和没有任何doc的空chunk没有区别。均衡分发保证每个shard的chunk数量是大致相同的。因此,片键的选择直接影响分片的好坏。

例如:一个MongoDB分片集群有3个shard,分别是shard1,shar2,shard3。片键的最小值是:$MinKey,最大值是:$MaxKey。包含端值$MinKey的chunk是最小块,包含端值$MaxKey的chunk是最大块。

1,升序片键

升序片键类似date字段或者_id字段,是一种随着时间稳定增长的字段。假如分片的字段是_id字段,集合foo中存在10个doc,每个shard中存在一个数据块,分别是:chunk1:$MinKey-3,chunk2:4-8,chunk3:9-$MaxKey。

使用升序片键的劣势是:每次插入一个新的doc,都会插入到最大块中,这会导致所有的写请求都会被路由到同一个分片,导致最大块不断增长,不断被拆分,然后不断被移动到其他分片中,导致数据的写入不均衡,块移动会额外增加Disk的写数量。使用升序片键的优势是:按照片键进行范围读时,性能高。

2,随机片键

随机片键是指片键的值不是固定增长,而是一些没有规律的键值。由于写入数据是随机分发的,各分片增长的速度大致相同,减少了chunk 迁移的次数。使用随机分片的弊端是:写入的位置是随机的,如果使用Hash Index来产生随机值,那么范围查询的速度会很慢。

3,基于分组的片键

基于分组的片键是两字段的复合片键,第一个字段用于分组,该字段的势最好是比较低的,势是在同一字段中不同值(distinct value)的数量或所占的比例;第二个字段用于自增,该字段最好是自增字段。这种片键策略是最好的,能够实现多热点数据的读写。

单个mongod 在处理升序写请求时是最有效的,数据只需要写入到集合的末尾。基于分组的片键,将数量不多的分组分布在分片集群中,每个shard只有少量的chunk,这样能够将数据的写操作分布在分片集群中的每个shard上,在单个shard上,以升序方式读写数据。一个shard上的分组太多,写请求就相当于随机写了,反而不好。

二,按照片键范围进行定向分发

如果希望特定范围的chunk被分发到特定的分片中,可以为分片添加tag,然后为tag指定相应的片键范围,这样,如果一个doc属于tag的片键范围,就会被定向到特定的shard中。

1,为shard指定tag

sh.addShardTag("shar1","shard_tag1");
sh.addShardTag("shar2","shard_tag2");
sh.addShardTag("shar3","shard_tag2");

2,为tag指定片键范围

sh.addTagRange(
"db_name.collection_name",
{field:"min_value"},
{field:"max_value"},
"shard_tag"
)

每个shard的tag可以使用任意数量的tag,MongoDB的均衡器在移动块时,会将特定片键范围的chunk移动到特定的shard上。
三,手动进行数据的分发

MongoDB内置均衡器(balancer),自动实现数据块的拆分和移动,有时,可以关闭balancer,使用moveChunk命令手动移动数据块。

1,关闭balancer

连接到一个mongos,更新config.setting命名空间

use config
db.setting.update({"_id":"balancer"},{"enabled":false},true) --or
sh.setBalancerState(false);

2,拆分块
拆分块是指新增一个边界点,将一个chunk在边界点处拆分成两个chunk。在MongoDB中,将片键从小到大排序,边界值属于右边的chunk。

sh.splitAt("db_name.collection_name",{sharded_filed:"new_boundary_value"})

3,移动块
MongoDB将包含指定文档的chunk移动到指定的shard上,必须使用片键来查找所要一定的chunk。

sh.moveChunk("db_name.collection_name",{sharded_filed:"value_in_chunk"},"new_shard_name")

4,启用balancer

sh.setBalancerState(true)

5,刷新mongos的缓存

在Application layer 和数据存储之间,存在一个Query Router,即mongos,mongos会在第一次启动或分片的元数据被更新之后,从config server 同步配置数据,并缓存在mongos中。有时,mongos无法从config server上及时同步最新的配置信息,导致无法路由到相应的chunk,不能返回正确的数据,可以使用flushRouterConfig 命令手动刷新mongos的缓存

db.adminCommand({"flushRouterConfig":1})

参考文档:

Sharding

MongoDB 数据分发的更多相关文章

  1. MongoDB 分片键分类与数据分发

    In sharded clusters, if you do not use the _id field as the shard key, then your application must en ...

  2. [更新]跨平台物联网通讯框架 ServerSuperIO v1.2(SSIO),增加数据分发控制模式

    1.[开源]C#跨平台物联网通讯框架ServerSuperIO(SSIO) 2.应用SuperIO(SIO)和开源跨平台物联网框架ServerSuperIO(SSIO)构建系统的整体方案 3.C#工业 ...

  3. MongoDB 数据迁移和同步

    MongoDB 数据迁移和同步 MongoDB的数据同步 复制 mongodb的复制至少需要两个实例.其中一个是主节点master,负责处理客户端请求,其余的都是slave,负责从master上复制数 ...

  4. mongoDB 数据导出与导入

    一.导出 命令格式:在mongodb/bin目录下 mongoexport -h IP --port 端口 -u 用户名 -p 密码 -d 数据库 -c 表名 -f 字段 -q 条件导出 --csv ...

  5. MongoDB副本集配置系列十一:MongoDB 数据同步原理和自动故障转移的原理

    1:数据同步的原理: 当Primary节点完成数据操作后,Secondary会做出一系列的动作保证数据的同步: 1:检查自己local库的oplog.rs集合找出最近的时间戳. 2:检查Primary ...

  6. mongodb数据文件内部结构

    有人在Quora上提问:MongoDB数据文件内部的组织结构是什么样的.随后10gen的工程师Jared Rosoff出来做了简短的回答. 每一个数据库都有自己独立的文件.如果你开启了director ...

  7. 用elasticsearch索引mongodb数据

    参照网页:单机搭建elasticsearch和mongodb的river 三个步骤: 一,搭建单机replicSet二,安装mongodb-river插件三,创建meta,验证使用 第一步,搭建单机m ...

  8. MongoDB学习笔记(三) 在MVC模式下通过Jqgrid表格操作MongoDB数据

    看到下图,是通过Jqgrid实现表格数据的基本增删查改的操作.表格数据增删改是一般企业应用系统开发的常见功能,不过不同的是这个表格数据来源是非关系型的数据库MongoDB.nosql虽然概念新颖,但是 ...

  9. Mongodb数据备份恢复

    Mongodb数据备份恢复 一.MongoDB数据库导入导出操作 1.导出数据库 twangback为备份的文件夹 命令: mongodump -h 127.0.0.1[服务器IP] -d advie ...

随机推荐

  1. mysql开启远程访问权限

    1. //登录数据库 mysql -u root -pvmwaremysql>use mysql; //%为所有ip都可以远程访问 mysql>update user set host = ...

  2. webdav不识别软链接?解决办法?

    webdav不识别软链接?解决办法? 在使用webdav实现公网存储共享的时候,发现webdav并不支持软链接的共享,如下源代码可以100%确定这个问题 /* ### for now, only pr ...

  3. MongoDB实现分页(两种方法)

    1.插入实验数据 偷懒用下samus,100条. ; i < ; i++) { Document doc = new Document(); doc["ID"] = i; d ...

  4. unison+inotify-tools触发式双向自动同步

    双向实时数据同步部署 首先添加服务器ssh信任,即免秘钥登陆 Web1:192.168.10.36 Web2:192.168.10.37 分别在web1和web2上执行以下命令 mkdir ~/.ss ...

  5. seajs学习一天后的总结归纳

    公司项目最近需要将js文件迁移到seajs来进行模块化管理,由于我以前主要接触模块化开发是接触的AMD规范的requireJS,没有接触过CMD规范,而且在实际项目中还没有用过类似技术.于是,我非常兴 ...

  6. MYSQL的安装

    1.将mysql的安装文件放入虚拟机 2.搭建yum库 3.依次安装mysql的5个文件 最后一个server需要的依赖太多,所以用yum进行安装. 6.进行mysql的重置 mysql_instal ...

  7. 纯css来实现提示框

    用js用多了,就疏忽了最基本的css了---用title属性来实现提示框.下面言归正传------如何用css实现提示框: 1.利用title属性来实现鼠标滑过某个元素时,实现提示整段内容的功能(利用 ...

  8. C语言dll文件的说明以及生成、使用方法

    最近在搞一些小项目,由于要涉及到跟其它语言进行交互,动态链接库变成了不二的选择.为此也查阅了很多资料,将动态链接库的相关知识在此做一个整理. 一.动态链接库概述 动态链接库(Dynamic Link ...

  9. apk 反编译

    http://blog.csdn.net/vipzjyno1/article/details/21039349/ [置顶] Android APK反编译就这么简单 详解(附图) 标签: android ...

  10. web api Route属性定义

    ASP.NET Web API路由,简单来说,就是把客户端请求映射到对应的Action上的过程.在"ASP.NET Web API实践系列03,路由模版, 路由惯例, 路由设置"一 ...