原文:http://blog.nosqlfan.com/html/3223.html

RabbitMQ是当成应用比较广泛的队列服务系统,其配套的客户端和监控运维方案也比较成熟。BoxedIce的队列服务从今年四月开始从RabbitMQ切换到了MongoDB上,并一直稳定运行至今,下面是BoxedIce对队列系统的一个讨论PPT及相关叙述。分享给大家。

为什么要使用队列系统?

  • 因为一些任务需要在后台执行,让调用者不需要等待其完成就能返回。比如给用户发送邮件,短信之类的操作。
  • 还有就是一个大系统内部的通信,可能会采用队列的方式传递消息。

对队列系统有哪些要求?

  • 应对任务处理者:通常会有一些进程从队列里获取消息进行处理,而且通常这些进程都会启动很多个。所以队列需要能够处理并发的数据请求操作。
  • 原子性:队列中的元素只能被取出一次,必须保证每次读取队列中元素进行操作和删除这个元素是原子性的。
  • 快速:队列系统要能够快速地处理元素的写入和读取操作。
  • 垃圾回收能力:如果一个任务处理到一半死掉了,那么必须能有方法监测到并且将这个任务重新放入队列中。

关于任务处理

任务处理进程的工作,就是从队列中读出消息,并且处理这个消息。所以它需要一种能够从队列中取出元素进行处理的能力。RabbitMQ提供了AMQP协议,目前已经有许多基于此协议的客户端了,相对的,MongoDB基于其Mongo Wire Protocol协议也拥有丰富的客户端支持。

BoxedIce在使用RabbitMQ时是用的pika客户端,转为MongoDB后使用的是pymongo。这两个协议相对比,pymongo的开销要小很多。

对于原子性,RabbitMQ通过对consume/ack协议的支持来实现。而由于MongoDB只支持对单个文档的原子性个性,所以你可以使用其findAndModify 命令,简单语法如下:

db.runCommand( { findAndModify : collection, { options } } )

这里的options是一个数组,其包含下面一些元素:

  • where:是一个查询条件,比如在我们的例子里,这个查询条件是{‘where’ { ‘inProg’: false, ‘done’: false } }操作会针对查询到的第一个元素进行。
  • sort:是对查询结构的排序,可以设置查询返回结果是按哪种条件排序的。比如你可以设置一个消息优先级,然后按优先级的倒序排序,让优先级高的消息优先进行处理。
  • update:这是标明你需要如何个性这个元素,在我们的例子里,我们设置其inProg标识为true,标 明正在处理中,设置处理时间t为当前时间,这个时间会用在垃圾回收中。如下:{‘update’ : {‘$set’ : { ‘inProg’ : true, ‘t’ : new Date() } } }

垃圾回收

上面我们在处理消息的时候会将其inProg设置为true表示正在处理,当成功处理完成后,再将done设置为true,但如果处理过程中出现问 题,就会导致一个inProg为true但是done永远为false的任务。这时候就需要垃圾回收策略通过检查处理时间t来进行垃圾回收处理了。

now = datetime.datetime.now()
difference = datetime.timedelta(seconds=10)
timeout = now - difference queue.find({'inProg' : True, 'start' : {'$lte' : timeout} })

比如上面的代码,我们通过判断t是否是在当前时间10秒以前来判断是否过期(10秒都未处理完,我们认为任务处理失败),这些失败的消息我们可以进行相关的处理,让它重新加入到消息队列中。

其它的一些考虑

除了上面说到的速度,原子性等特性,对于一个队列系统,还是有一些其它方面需要考虑的。

  • 容错性:MongoDB的replica sets架构提供了整体的高可用性。当其被用作队列时,也同样继承了这一我。而RabbitMQ并没有内置的支持。目前在RabbitMQ 2.6.0中有相关的支持
  • 一致性:MongoDB默认会一分钟将数据flush到磁盘,但其同时提供一个默认100ms的操作日志可以增强其单机的可靠性。可以缓解宕机时数据丢失导致不一至的情况。如果你对一致性要求非常高,你也可以使用MongoDB的getLastError命令来保证你的每次操作都写入操作日志或者磁盘上才返回成功。
  • 扩展性:我们使用capped collection来做消息队列,所以老数据的清除是自动的。在MongoDB中可以通过sharding方式来实现数据的横向扩展,但是sharding并不支持用于capped collection。你可以自己选择自己需要的应用方式。

用MongoDB取代RabbitMQ(转)的更多相关文章

  1. 【转】MongoDB资料汇总专题

    1.MongoDB是什么 MongoDB介绍PPT分享 MongoDB GridFS介绍PPT两则 初识 MongoDB GridFS MongoDB GridFS 介绍 一个NoSQL与MongoD ...

  2. MongoDB资料汇总专题[转发]

    转发下..这个哥收集的很全 MongoDB资料汇总专题 作者:nosqlfan http://blog.nosqlfan.com/html/3548.html 最后更新时间:2013-04-22 1. ...

  3. MongoDB资料汇总(转)

    原文:MongoDB资料汇总 上一篇Redis资料汇总专题很受大家欢迎,这里将MongoDB的系列资料也进行了简单整理.希望能对大家有用. 最后更新时间:2013-04-22 1.MongoDB是什么 ...

  4. MongoDB资料汇总专题(转)

    原文地址:http://blog.nosqlfan.com/html/3548.html 1.MongoDB是什么 MongoDB介绍PPT分享 MongoDB GridFS介绍PPT两则 初识 Mo ...

  5. elasticsearch与mongodb分布式集群环境下数据同步

    1.ElasticSearch是什么 ElasticSearch 是一个基于Lucene构建的开源.分布式,RESTful搜索引擎.它的服务是为具有数据库和Web前端的应用程序提供附加的组件(即可搜索 ...

  6. MongoDB资料汇总专题

    原文地址:http://bbs.chinaunix.net/thread-3675396-1-1.html 上一篇Redis资料汇总专题很受大家欢迎,这里将MongoDB的系列资料也进行了简单整理.希 ...

  7. Linux安装ElasticSearch与MongoDB分布式集群环境下数据同步

    ElasticSearch有一个叫做river的插件式模块,可以将外部数据源中的数据导入elasticsearch并在上面建立索引.River在集群上是单例模式的,它被自动分配到一个节点上,当这个节点 ...

  8. (原)MongoDB在系统中的使用

    序)Nosql并不是要取代原有的数据产品,而是为不同的应用场景提供更多的选择. 一)结构类型 传统数据库的领域在于结构化文档,对于非结构化文档和半结构化文档,它能处理,但是有一定的缺陷,那么什么又是结 ...

  9. [奇思异想]使用RabbitMQ实现定时任务

    背景 工作中经常会有定时任务的需求,常见的做法可以使用Timer.Quartz.Hangfire等组件,这次想尝试下新的思路,使用RabbitMQ死信队列的机制来实现定时任务,同时帮助再次了解Rabb ...

随机推荐

  1. CentOS命令top下你不一定懂的cpu显示信息

    在使用top命令的时候会看到这么一行: 里面的各个值分别是什么意思呢? 今天被问到这个问题,发现答的不是很清楚.果然啊,天天用最多的top命令都还没摸透...惭愧...于是就查了些资料: 官方解释 C ...

  2. JavaSE(十)之反射

    开始接触的时候可能大家都会很模糊到底什么是反射,大家都以为这个东西不重要,其实很重要的,几乎所有的框架都要用到反射,增加灵活度.到了后面几乎动不动就要用到反射. 首先我们先来认识一下对象 学生---- ...

  3. sqlldr导入数据(以PostgreSql>>>Oracle为例)

    1.在目标数据库中创建表 1.1点击源表,复制创建语句 1.2 修改数据类型以匹配目标数据库,如: 字符串类型:character varying(20)>>>varchar2(20 ...

  4. NSArray打印汉字的方法

    (1) NSArray打印汉字 通过重载NSArray的- (NSString *)descriptionWithLocale:(id)locale方法 方法体例如以下: //依据设置的locale ...

  5. 学习 TList 类的实现[6]

    实现 TMyList.Add 函数. TList 中的 Add 函数用到了一个 Grow 方法, 它的原理是元素越多就为以后准备更多内存, 我们这里省略为预留 4 个元素的内存; TList 中的 A ...

  6. linux环境判断字符串是否为非空

    需求描述: 今天帮同事调整脚本,涉及到判断一个字符串为非空的,在此记录下. 操作过程: 通过-n来判断字符串是否为非空,如果为非空那么就是真 #!/bin/bash Str1='MyTest' if ...

  7. ios 判断GPS是否是在中国境内

    博文转载至 http://blog.csdn.net/cuibo1123/article/details/45691631 ZCChinaLocation 基本思路是:把整个行政区域划分为几个小的矩形 ...

  8. mysq对存在null值的字段排序

    1.建立学生表,建表sql如下: ),age int); 2.插入几条数据,包括id字段值为null的 ,),(,),(,),(),(); 3.我们查询下,可以看到存在id字段为空的值: 4.对学生表 ...

  9. Linux学习——定义命令行函数(cd .. -> ..)

    在使用shell的时候,每天要面对各种命令行,比如ls , cd .. 等 抱着简单,可依赖的思想.有些可以简化的操作可以要通过在 ~/.bashrc 中进行添加: 1. cd .. -> .. ...

  10. c++ 重载、重写、重定义(隐藏)

    1.重载overload:函数名相同,参数列表不同. 重载只是在类的内部存在,或者同为全局范围.(同名,同参函数返回值不同时,会编译出错.因为系统无法知晓你到底要调用哪一个.)   2.重写overr ...