MQ对比之RabbitMQ & Redis

消息队列选择:RabbitMQ & Redisgit

RabbitMQ

RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现的产品,RabbitMQ是一个消息代理,从“生产者”接收消息并传递消息至“消费者”,期间可根据规则路由、缓存、持久化消息。“生产者”也即message发送者如下简称P,相对应的“消费者”乃message接收者如下简称C,message经过queue由P到C,queue存在于RabbitMQ,可存储尽量多的message,多个P可向同一queue发送message,多个C可从同一个queue接收message

RabbitMQ架构:github

img

组件:golang

  • Message (消息):RabbitMQ 转发的二进制对象,包括Headers(头)、Properties (属性)和 Data (数据),其中数据部分不是必要的;
  • Producer(生产者): 消息的生产者,负责产生消息并把消息发到交换机Exhange的应用;
  • Consumer (消费者):使用队列 Queue 从 Exchange 中获取消息的应用;
  • Exchange (交换机):负责接收生产者的消息并把它转到到合适的队列;
  • Queue (队列):一个存储Exchange 发来的消息的缓冲,并将消息主动发送给Consumer,或者 Consumer 主动来获取消息。
  • Binding (绑定):队列 和 交换机 之间的关系。Exchange 根据消息的属性和 Binding 的属性来转发消息。绑定的一个重要属性是 binding_key。
  • Connection (链接)和 Channel (通道):生产者和消费者须要和 RabbitMQ 创建 TCP 链接。一些应用须要多个connection,为了节省TCP 链接,可使用 Channel,它能够被认为是一种轻型的共享 TCP 链接的链接。链接须要用户认证,而且支持 TLS (SSL)。链接须要显式关闭。

Redis

Redis 是彻底开源免费的,遵照BSD协议,是一个高性能的key-value数据库。数据库

Redis 与其余 key - value 缓存产品有如下三个特色:ubuntu

  • Redis支持数据的持久化,能够将内存中的数据保存在磁盘中,重启的时候能够再次加载进行使用。
  • Redis不只仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
  • Redis支持数据的备份,即master-slave模式的数据备份。

Redis 优点

  • 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
  • 丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操做。
  • 原子 – Redis的全部操做都是原子性的,意思就是要么成功执行要么失败彻底不执行。单个操做是原子性的。多个操做也支持事务,即原子性,经过MULTI和EXEC指令包起来。
  • 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过时等等特性。

首先Redis的设计是用来作缓存的,可是因为它自身的某种特性使得他能够用来作消息队列(Redis的List数据结构比较适合作MQ)。它有几个阻塞式的API可使用,正是这些阻塞式的API让他有作消息队列的能力。 另外作消息队列的其余特性,例如FIFO也很容易实现,只须要一个list对象从头取数据,从尾部塞数据便可实现。 Redis能作消息队列得益于它的list对象blpop brpop接口以及Pub/Sub(发布/订阅)的某些接口。他们都是阻塞版的,因此能够用来作消息队列。缓存

RabbitMQ和Redis的简单对比

RabbitMQ和Redis均可以作队列,可是他们仍是有区别的。好比,Redis的消息队列,若是在从队列pop出去的时候,worker处理失败的话,数据不会回到队列中,须要从业务中手动把失败的处理数据push到队列中;而RabbitMQ能够自动处理失败的worker使数据不丢失;RabbitMQ还能够保证数据在传输过程当中持久化,在通道和队列中的数据能够设置为持久化。首先Redis严格来讲并非消息队列,它是一个内存数据库,不过由于其某些特性适合用来充当队列,因此也多被用于作简单的mq, Redis之父却是开发了个真正的消息队列disque,有兴趣能够看看。数据结构

相比起Redis,RabbitMQ有更加完善的MQ机制,这里咱们仅讨论消息的durable(持久性),后续一系列其余机制有时间再交流。架构

RabbitMQ有一个消息确认机制来保证消息的不丢失:客户端从队列中取出消息以后,可能须要一段时间才能处理完成,若是在这个过程当中,客户端出错了,异常退出了,而数据尚未处理完成,那么很是不幸,这段数据就丢失了,由于RabbitMQ默认会把此消息标记为已完成,而后从队列中移除,消息确认是客户端从RabbitMQ中取出消息,并处理完成以后,会发送一个ack告诉RabbitMQ,消息处理完成,当RabbitMQ收到客户端的获取消息请求以后,或标记为处理中,当再次收到ack以后,才会标记为已完成,而后从队列中删除。当RabbitMQ检测到客户端和本身断开连接以后,还没收到ack,则会从新将消息放回消息队列,交给下一个客户端处理,保证消息不丢失,也就是说,RabbitMQ给了客户端足够长的时间来作数据处理。性能

RabbitMQ demo之生产者消费者

生产者

img

消费者(不发送ack,模拟程序中断)

imgno-ack = False,若是消费者遇到状况(its channel is closed, connection is closed, or TCP connection is lost)挂掉了,那么,RabbitMQ会从新将该任务添加到队列中。spa

正常发送ack的消费者:

img发送ack则被认为是正常消费message的consumer,则RabbitMQ会把message从队列中移除,此时再看队列中已经没有消息。

关于RabbitMQ的其余features,如 Publish/Subscribe、Routing、Topics和RPC等,有兴趣能够Google。除了RabbitMQ除了Python的实践外,也可考虑其余语言的实践,这里提供另一个语言golang的选择,可参考Ubuntu14.04+RabbitMQ3.6.3+Golang的最佳实践,这个文章讲的很是详尽,实践意义比较具备参考价值,有兴趣能够阅览一番。