MongoDB报表实例计划选型51CTO博客 - 威尼斯人

MongoDB报表实例计划选型51CTO博客

2019年03月10日12时36分51秒 | 作者: 若云 | 标签: 报表,实例,运用 | 浏览: 1277

MongoDB报表实例计划选型


布景介绍


在咱们的出产环境运用的是仿制集,为了将数据库效劳器的事务压力分摊,咱们将数据库拆分到了不同的仿制集上运转。


咱们在MongoDB仿制集上运转运用程序,有时分有报表需求,惯例用处是取得用户行为的剖析,还有其他商业定制目标数据;有查找引擎的查询需求,运用Solr从oplog.rs获取增量数据更新产品信息的索引。


这些报表查询和查找引擎的查询需求,尽量不能影响到线上的事务正常运转,因而不能直接在出产数据库上运转报表。经过开发和运维评论之后,在项目建立之初,计划距离报表使命致使不会影响到出产使命。


来谈谈混杂出产和报表的问题


作业集(workingset),是MongoDB在任何的时刻距离读取和写入的整个数据库的一个子集。出产环境中的活泼用户操作文档数据,操作体系将它们坚持在物理内存中。


留意:不要让你的作业集添加大过内存!能够运用MongoDB的监控效劳Cloud Manager监控你的实例。假如的确呈现这个问题,你需求分片,因而容量规划是很重要的,能够作为独立的专题来讲。即便数据库巨细是可用内存的数百或数千倍,假如你在前期合理规划了架构并优化了索引,MongoDB相同也能高效运转。在作业集外的数据会坚持和磁盘上共同,当用户空闲时,他们操作的文档将会不再运用,所占用的内存用于新的活泼用户的内存恳求。


报表运用会查询许多的数据,一般不会重复拜访相同的数据,每个报表运用或许彻底拜访不同的数据调集。这意味着需求继续供给内存给新的文档读取恳求。假如你将报表运用和出产运用放在相同的实例上运转,报表运用将会与你的出产运用抢夺内存,继续不断地恳求活泼用户的数据,而你的出产运用继续不断的加载它(getmore)。那么数据库效劳器功能将发作动摇。


报表运用,将会有许多count、aggregate、mapReduce等聚合操作,这些操作关于MongoDB来说功率不高,因而将它与出产使命分隔是一个好的做法。


运用专属报表实例的仿制集


MongoDB仿制集具有在线持久性,经过仿制数据到一个调会集的一切节点,并对客户端供给无缝的毛病搬运。包括一个主节点供给写,而剩余的是只读副本。当条件需求的时分推举决议哪个节点是主。仿制集应该包括一个奇数成员协助快速推举。


判别不行达的机器是否宕机根本上无法判别,有或许被网络被分区了。因而假如仿制会集的大多数节点下线了(也就是说,3个成员中的2个下线),即便一个健康的主节点保存,它会降级为一个只读的副本。不这么做或许导致多个机器在一个网络分区的状况下定义它们自己为主节点,呈现多个主节点,导致可怕的数据不共同。


因而一个仿制集包括至少3个成员,供给一个机器失利的过错忍受。


在MongoDB官方的文档中,引荐约束报表查询到专属节点。报表根本不需求写操作,而是计算终究共同性数据。假如提取的数据有秒级或分级延时,每日的报表是不答应的。假如你的计数计算丢掉了一些操作,这将导致报表数据不精确。


你能够在MongoDB仿制集环境构建专属的报表节点,计划有躲藏的仿制集成员hidden member或许读偏好read preference设置相关的标签调集tag sets。榜首种办法更简略,第二种办法更灵敏。


下图是运用专属节点供给报表需求的架构图:



躲藏成员计划


参阅:https://docs.mongodb.com/manual/tutorial/configure-a-hidden-replica-set-member/


躲藏成员是仿制集的一部分,可是不能成为主,而且对客户端运用程序不行见。躲藏成员能够在推举中投票。


一个仿制集的躲藏成员被装备为priority: 0,是为了阻挠它们被推举为主。设置hidden: true,即便他们指定了一个读偏好为secondary,也会阻挠客户端衔接到仿制集路由读操作到它。


从一个躲藏成员读数据,你只能经过直连该躲藏成员拜访,并指定slave_ok,而不能经过MongoReplicaSetClient类。


躲藏成员设置


你能够运用mongo shell来躲藏一个存在仿制集的成员:

$ mongo admin -uxucy -p
PRIMARY> conf = rs.config()
{ "_id" : "test", "version" : 21, "members" : [ { "_id" : 0, "host" : "xucy.local:27017", }, { "_id" : 1, "host" : "xucy.local:28017", }, { "_id" : 2, "host" : "xucy.local:29017", } ] }
PRIMARY> conf.members[1].priority = 0
PRIMARY> conf.members[1].hidden = true
PRIMARY> conf.version += 1
PRIMARY> rs.reconfig(conf)


xucy.local:28017现在躲藏了,它将继续仿制操作和像平常相同在推举中投票,可是衔接到仿制集的客户端将不会从它读取,即便xucy.local:29017下线。


Ruby版的报表运用衔接代码示例:

require mongo
reporting = Mongo::MongoClient.new("xucy.local", "28017", slave_ok: true)
reporting[my_application][users].aggregate(...)


约束阐明


运用躲藏的成员是一个最简略的办法,装备实例用于专属的作业负载,像报表和查找引擎拜访,可是运用上有一些约束需求阐明的。


躲藏成员不能在紧迫状况下读取


带有2个一般和1个躲藏成员在一个仿制会集,关于写的过错忍受等价于一个惯例的3个成员的调集。可是,你失掉两个节点,你的出产运用将不能高雅的降级到只读形式,由于你的躲藏成员将不答应仿制集客户端读取。假如你仅仅喜爱躲藏成员拜访简略,土豪计划是运用一个5成员(带有一个躲藏成员)的仿制集。


关于仿制集的包装代码不能被运用


许多团队创立运用定制的包装代码时,运用MongoDB驱动供给的仿制集衔接拜访办法,添加仿制集衔接的根本信息给客户端。由于你需求运用独立衔接到你的报表实例,你不能重用它。



标签成员计划


参阅:https://docs.mongodb.com/manual/tutorial/configure-replica-set-tag-sets/


标签成员,愈加杂乱,可是,是更灵敏的办法,用于路由报表查询到一个专属节点去运用标签和读偏好。


设置一个成员为priority: 0,阻挠它被推举为主,可是不设置它为躲藏,分配一个标签use: reporting:

PRIMARY> conf = rs.config()
{ "_id" : "test", "version" : 21, "members" : [ { "_id" : 0, "host" : "xucy.local:27017", }, { "_id" : 1, "host" : "xucy.local:28017", }, { "_id" : 2, "host" : "xucy.local:29017", } ] }
PRIMARY> conf.members[1].priority = 0
PRIMARY> conf.members[1].tags = { "use": "reporting" }
PRIMARY> conf.version += 1
PRIMARY> rs.reconfig(conf)


在这种状况下,xucy.local:28017绝不会成为主。可是,当其他两个机器变得不行达,你的运用还能处理读恳求到报表效劳器。它会继续运转,不会导致你的报表运用在这样一个事情期间暂停。


Python版报表运用衔接代码示例:

from pymongo import MongoReplicaSetClient
from pymongo.read_preferences import ReadPreference
rep_set = MongoReplicaSetClient( xucy.local:27017,xucy.local:28017,xucy.local:29017, replicaSet = test, read_preference = ReadPreference.SECONDARY, tag_sets = [{use:reporting}] )
rep_set.my_application.users.aggregate(...)


关于报表运用来说,在主可用的状况下,保证尽量不要在剩余的仅有的辅佐成员上运转报表运用,由于这样将报表和出产混合在一起了。


以上只发送报表查询到符号有use: reporting的辅佐成员,而且假如没有可用的主,咱们应该从根本上阻挠继续运转。在实践中,假如你发现没有主,你应该抛出反常并在你的扩展代码中处理它们。还要做好状况的监控,如:reporting_system.ok()。当发现反常时进行分支处理。


好处和考虑


运用标签和读偏好相对躲藏成员来说,带来必定的灵敏性。


简略添加报表实例


由于你的衔接代码是可定义的,而不是指定到一个专门的主机。你能够添加更多节点为报表实例,只需求添加并符号他们,像这样:

PRIMARY> rs.add({_id:3, host:"xucy.local:30017", priority:0, tags:{use:reporting}})


你本来的代码将会运用到新的报表实例,而且仿制集将继续运转,不必触发推举和从客户端断开衔接。


报表实例能够被越过或删去


当你想将现在运用的报表实例供给给其他运用时,报表符号在必要时能够被移动,或许移除。像这样的一个重新装备将会触发推举,偏重连一切客户端,这是能够承受的。留意:这是一个逆向的办法,经过添加常用出产可用实例,分发出产读到副本成员。


一些驱动需求手艺同步


查看你的驱动文档,例如,Ruby驱动(像1.9.2),不会改写副本集的视图,除非客户端像这样运用refresh_mode: :sync显式初始化。



Solr生成全文索引


MongoDB仿制集装备简略、简略上手是我喜爱MongoDB的原因之一。关于MongoDB报表实例,不管你运用躲藏成员仍是标签成员,开发和布置都十分简略。咱们在出产环境也将报表实例用于Solr生成全文索引。


Solr是一个独立的企业级查找运用效劳器,它对外供给类似于Web-service的API接口。用户能够经过http恳求,向查找引擎效劳器提交必定格局的XML文件,生成索引;也能够经过Http Get操作提出查找恳求,并得到XML格局的回来成果。


读取报表实例的计划选型


期初的计划是运用mongo-connector集成MongoDB到Solr完成增量索引。( />

mongo-connctor是一款用于同步MongoDB数据到其他体系组件,比方它能同步数据到Solr、ElasticSearch或许其他MongoDB集群中去。它的完成原理是依据MongoDB的Replica Set仿制形式,经过剖析oplog日志文件到达终究的同步意图。装置装备发动进程可参阅 官方文档 。


由所以单进程版别的,功率对咱们其时来说不高,假如能改成运用多核功能的话或许好些。


MongoDB Tailable Cursors


MongoDB 有一个叫 Tailable Cursors的特性,它类似于tail -f 指令,你在一个Capped Collection上面履行查询操作,当操作完成后,你能够不封闭回来的数据Cursor,并继续地从中读出新参加的数据。


在高写入的Capped Collection上,索引不行用时,可运用Tailable Cursors。例如,MongoDB仿制运用了Tailable Cursors来获取Primary的尾oplog日志。


考虑以下与Tailable Cursors相关的行为:

  • Tailable Cursors不运用索引,并以天然排序回来文档。

  • 由于Tailable Cursors不运用索引,查询的初始扫描十分耗功能;可是,游标初始化完后,随后获取到的新添加的文档是很快速的。

  • Tailable Cursors假如遇到以下状况之一将会僵死或无效:

    • 查询无匹配成果。

    • 游标在调集尾部回来文档,随后运用程序删去了该文档。

僵死的游标id为0。


DBQuery.Option.awaitData


在运用TailableCursor时,此参数会在数据读尽时先堵塞一小段时刻后再读取一次并进行回来。


盯梢oplog的示例:

use local
var cursor = db.oplog.rs.find({"op" : "u", "ns" : "MyDB.Product"},{"ts": 1, "o2._id": 1}).addOption(DBQuery.Option.tailable).addOption(DBQuery.Option.awaitData);
while(cursor.hasNext()){
var doc = cursor.next();
printjson(doc);
};


2.6版的游标办法:

cursor.addOption()

https://docs.mongodb.com/v2.6/reference/method/cursor.addOption/


3.2版的游标办法:

cursor.tailable()

https://docs.mongodb.com/manual/reference/method/cursor.tailable/


咱们依据该特性,开发了Java运用程序,先初始化全量同步数据到Solr生成索引、记载同步时刻。然后经过Tailable Cursors读取oplog.rs比照前次记载的同步时刻,假如是新的改变,经过新的进程异步获取日志里记载的最新数据更新到Solr的文档里。



版权声明
本文来源于网络,版权归原作者所有,其内容与观点不代表威尼斯人立场。转载文章仅为传播更有价值的信息,如采编人员采编有误或者版权原因,请与我们联系,我们核实后立即修改或删除。

猜您喜欢的文章