MongoDB分片环境下的查询路由
来源:互联网 发布:淘宝怎么秒杀商品 编辑:程序博客网 时间:2024/05/23 00:05
根据2015-01-14官方文档快照翻译(v2.6.7 & v2.8.0-rc4)
翻译 shingo(6623662005@163.com)
在分片集群环境中,MongoDB通过mongos实例来路由读写操作。从应用的角度来说,mongos是访问集群的唯一入口,应用程序不能直接连接集群环境中的分片节点。
通过缓存config节点的元数据信息,mongos可以跟踪到数据在哪个分片上。mongos利用这些元数据信息将应用和客户端的操作路由到具体的mongod实例。mongos不提供持久化,并且只消耗很少的系统资源。
最常见的做法是将mongos实例和应用服务器部署在同一环境下,当然你也可以将mongos实例和分片节点放在一起,或者用专门的资源来运行它。
注意
2.1版更新。
一些使用aggregate 命令的聚合操作(即db.collection.aggregate()),会使得mongos 实例较之前的版本需要更多CPU资源。如果你的分片环境中大量使用了aggregation框架,那么你可能要更改部署架构来应对这部分性能上的调整。
路由过程
mongos如何决定由哪些分片来接收一个查询
mongos路由一个查询到集群中有两步:
- 1. 确定接收查询的分片列表。
- 2. 为所有目标分片建立一个游标。
在一些情况下,例如当shard key或shard key的某个前辍部分被当做查询条件的一部分时,mongos会将查询路由到分片集的某个子集下,其它时候,mongos将查询引向所有包含目标表数据的分片下。
(译者注:这里所说的shard key的某个前辍部分是指如果是复合key,那么从第一个字段开始按序往后的子集,这个子集对查询时尽可能精确的定位分片有很大帮助,子集越大定位越准。)
示例:
有下面的shard key:
{ zipcode: 1, u_id: 1, c_date: 1 }
根据集群中具体的chunk分布情况,mongos 可能会将查询路由到一部分分片上,如果查询包括以下字段:
{ zipcode: 1 }
{ zipcode: 1, u_id: 1 }
{ zipcode: 1, u_id: 1, c_date: 1 }
Mongos如何处理查询修改器
如果查询结果不需要排序,mongos会开启一个结果游标,从各个目标分片的游标“轮循”结果。
2.0.5版更新:在2.0.5之前的版本中,mongos一个接一个将游标从头滑到尾。
(译者注:2.0.5版之前mongos会循环所有目标分片返回的数据集,每一个数据库通过游标从头至尾;从2.0.5开始,mongos开启一个总的游标,每个数据集拿一条数据,循环往复。)
如果查询操作用sort()方法指定了排序规则,mongos 将$orderby选项传递给各个目标分片。在通过mongos将结果集返回客户端之前,数据库的主shard会接收所有结果数据,确定后执行合并排序。
如果查询操作用limit()限制结果集的大小,mongos 将这个限制传递给各个目标分片,在返回客户端之前再将整个结果集缩减到指定大小。
(译者注:如果数据够大,假设有n个目标分片,limit的参数为x,mongodb会至少扫描n*x条数据。不过在现实的场景中,limit的需求一般为分页,或是专门被指定的一个有限集,这个数在多数情况下不会太大。)
如果查询操作用 skip()方法指定要忽略的结果个数,mongos不会将这个忽略数传递给目标分片,而是从各分片检索出符合查询条件的所有结果,在组装最终结果集时再忽略指定数目的数据。但是如果它和limit()方法联合使用,mongos 将 limit的值加上skip()方法的值传递给目标分片,以此来提升这些操作的效率。
(译者注:limit+skip =每个分片上最终limit值,这也是为了规避查询条件的不同,以及多种因为数据分布引发的结果数据不准确的可能性。 Mongodb的翻页查询随着skip数量的增加性能会越来越差,其实有很多办法可以规避这种查询,比如在主键,或者例用某个字段来精确定位某一页的值范围。)
检测连向mongos的连接
要检测你客户端连接的mongodb实例是否是mongos,可以使用 isMaster 命令。当客户端连上mongos,isMaster返回一个带有msg字段的文档,且字段值为isdbgrid,类似下面这样:
{
"ismaster" : true,
"msg" : "isdbgrid",
"maxBsonObjectSize" : 16777216,
"ok" : 1
}
如果连接的是mongod实例,返回的文档不会包含isdbgrid字符串。
广播操作和目标操作
一般来说,分片环境里的操作有以下两类:
- · 向集群内所有包含某个表数据的分片广播
- · 基于shard key,有目标的选定某一个分片或某一部分分片
为了获得最佳的性能,尽可能的使用目标操作。而对于一些需要广播到所有分片的操作,如果可以的话在条件里加上shard key让它转变为目标操作。
广播操作
mongos会将查询广播到所有包含目标表数据的分片上,除非mongos能搞清楚哪个或哪些分片上存储着目标数据。
批量更新操作属于广播操作。
remove()操作一般也是广播操作,除非条件中指定了完整的shard key。
目标操作
所有insert()操作会定位到具体的一个分片。
所有单个 update() (包括upsert) 和remove() 也会定位到单独的分片。
重要
指定了justOne或 multi:false属性的,针对单个分片的update()和 remove() 操作,查询条件中必须包含shard key或_id字段,否则方法会报错。
对于包含shard key或包含一部分shard key的查询,mongos可以定位到具体的某个或多个分片上。这里提到的“一部分shard key”是指从shard key的第一个字段开始依次往后的前辍部分。举个例子,如果有下面的shard key:
{ a: 1, b: 1, c: 1 }
mongos 能够通过查询条件中完整的shard key或者下面两个条件来定位分片:
{ a: 1 }
{ a: 1, b: 1 }
由于数据分布的不同以及查询的多样性,mongos可能仍然会连接到多个分片[1]来完成查询。
[1]如果真的是因为数据分布上的原因,即使查询中包含shard key,mongos也会将查询路由到所有分片。
分片的和未分片的数据
分片是基于collection级的,你可以在同一个数据库内对多个collection做分片,或者对多个数据库开库分片功能。[2]但是在生产环境中,一般会有一些数据库和collection使用了分片功能,而其它未开启分片的数据库和collection会存储在单个分片上。
不管你的分片集群环境的数据架构如何,一定要确保所有操作都通过mongos路由到分片上。即使你的操作针对的是未分片的数据,影响不了分片数据,也要通过mongos来路由。
[2] 当配置分片功能时,需要使用enableSharding命令为数据库开启分片功能。这个操作也仅仅是为了让该数据库下的collection在分片时能执行shardCollection命令。
- MongoDB分片环境下的查询路由
- MongoDB分片环境下整体数据迁移解决方案
- 一.mongodb分片之win7环境下模拟多节点添加与移除分片
- mongodb分片环境开启认证
- mongodb 分片的思考
- mongodb的sharding(分片)
- Mongodb的分片部署
- mongodb 分片的思考
- (*)Mongodb的分片配置
- mongodb的分片
- mongoDB 分片的管理
- MongoDB的分片
- MongoDB的分片
- MongoDB的分片测试
- MongoDB分片的搭建
- MongoDB的分片集群
- mongodb的分片
- MongoDB的分片
- 杭电 2031 进制转换
- Java开发的23种设计模式
- iOS 屏幕适配frame 宏
- OGG-01296 Oracle GoldenGate Delivery for Oracle OGG-01668 Oracle GoldenGate Delivery for Oracle
- u-boot链接脚本解析
- MongoDB分片环境下的查询路由
- ios TableView设置背景图片
- HSSFWorkBooK用法
- 第一个标准Windows程序(个人一次写成的最简版本)
- 心得体会-----jenkins学习反思
- Python中的exec、eval使用实例
- 版本更新
- Python学习(第一周)
- iOS 注释方法