MongoDB 数据分发

在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 configdb.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

时间: 2024-12-14 18:05:03

MongoDB 数据分发的相关文章

MongoDB 数据迁移和同步

MongoDB 数据迁移和同步 MongoDB的数据同步 复制 mongodb的复制至少需要两个实例.其中一个是主节点master,负责处理客户端请求,其余的都是slave,负责从master上复制数据. master写处理:master负责接收写请求,具体的流程为: 如果开启journal功能,则先将写请求记录到journal中,然后批量执行,同时将操作记录到oplog中: 如果未开启journal功能,则对每个写请求进行单独操作,然后写入oplog. 注:oplog是幂等的,当有累加操作in

MongoDB数据文件内部结构

有人在Quora上提问:MongoDB数据文件内部的组织结构是什么样的.随后10gen的工程师Jared Rosoff出来做了简短的回答. 每一个数据库都有自己独立的文件.如果你开启了directoryperdb选项,那你每个库的文件会单独放在一个文件夹里. 数据库文件在内部会被切分成单个的块,每个块只保存一个名字空间的数据.在MongoDB中,名字空间用于区分不同的存储类别.比如每个collection有一个独立的名字空间,每个索引也有自己的名字空间. 在一个块中,会保存多条记录,每条记录是B

Mongodb数据库命令端常用操作

查询操作 Mongodb-SpringMvc下Query数据库操作SQL http://blog.csdn.net/xiaohulunb/article/details/27828381 1.查询所有 > db.foo.find() { "_id" : ObjectId("5389aa1df06b88aaa313746a"), "name" : "yiwa", "age" : 25, "us

使用Kettle增量抽取MongoDB数据实践

需求: 增量抽取MongoDB数据并加载到MSSQL 由于不能使用关系型数据库的自定义SQL, 所以主要遇到的问题有: 增量时间的查询和参数控制 ETL的批次信息和调用参数的写入 第一个问题的解决如下: 使用命名参数在Query页中进行过滤, 一开始会担心${}的引用方式会用Mongo的语法冲突, 测试后发现运行正常 第二个问题: 先为结果增加常量值, 如常量值固定则直接写死, 不固定的常量值先设置为空串, 在后面使用字符串替换组件传入命名参数, 最后用字段选择把空串的常量值移除

MongoDB数据表基本操作

MongoDB数据表基本操作 查看全部数据表 > use ChatRoom switched to db ChatRoom > show collections Account Chat system.indexes system.users 创建数据表 > db.createCollection("Account") {"ok":1} > db.createCollection("Test",{capped:true,

MongoDB 数据文件备份与恢复

备份与恢复数据对于管理任何数据存储系统来说都是非常重要的. 1.冷备份与恢复——创建数据文件的副本(前提是要停止MongoDB服务器),也就是直接copy MongoDB将所有数据都存储在数据目录下,默认是/data/db/(Windows下是C:\data\db\),启动MongoDB时也可以用--dbpath指定我们自己设置的数据存储目录. 备份MongoDB数据:只要简单的创建数据存储目录的副本就可以了,直接copy一份. 恢复MongoDB数据:在MongoDB启动时用--dbpath指

将mongodb 数据指定字段导出,然后指定字段导入mysql 实例 及相关问题解决

需求:将mongodb 数据指定字段导出,然后再指定字段导入mysql  表中 直接上图吧, 最后 会将遇到几个问题及解决方案贴出,以便遇到类似问题可以迅速解决(期间所用命令具体用法不在本文详解之内) 将mongodb 数据指定字段导出,所用命令Mongoexport ,具体查阅官方文档: 导出指定二级字段 Mongodb /opt/mongodb/bin/mongoexport  --host yourip  --port yourport   -d app_form -c applicati

MongoDB数据修改总结

MongoDB数据修改总结 2013-10-26 10:08:30      我来说两句    来源:huhui的专栏    收藏  我要投稿 MongoDB数据修改总结 1.前言 最近在学习MongoDB,数据修改这一部分的内容较多,命令比较繁琐,所以将一些常用的修改命令总结在这篇博客中,方便今后学习的查阅. 2.命令总结 1). insert() db.collection.insert(x)  x就是要更新的对象,只能是单条记录,如: [plain] db.collection.inser

使用hadoop mapreduce分析mongodb数据

使用hadoop mapreduce分析mongodb数据 (现在很多互联网爬虫将数据存入mongdb中,所以研究了一下,写此文档) 版权声明:本文为yunshuxueyuan原创文章.如需转载请标明出处: http://www.cnblogs.com/sxt-zkys/QQ技术交流群:299142667 一. mongdb的安装和使用 1. 官网下载mongodb-linux-x86_64-rhel70-3.2.9.tgz 2. 解压 (可以配置一下环境变量) 3. 启动服务端 ./mongo