MQ对比之RabbitMQ & Redis

  |   0 评论   |   6,453 浏览

消息队列选择:RabbitMQ & Redis

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 架构:

img

组件:

  • 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 缓存产品有以下三个特点:

  • 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 会重新将该任务添加到队列中。

正常发送 ack 的消费者:

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

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


微信公众号

潘建锋

关于版权和转载

本文由 潘建锋 创作,采用 署名 4.0 国际 (CC BY 4.0) 国际许可协议进行授权。
本站文章除注明转载/出处外,均为本站原创或翻译,转载时请务必署名,否则,本人将保留一切追究责任的权利。
署名 4.0 国际 (CC BY 4.0)

转载规范

标题:MQ对比之RabbitMQ & Redis
作者:潘建锋
原文:https://taohuawu.club/mq-rabbit-redis

关于留言和评论

如果您对本文《MQ对比之RabbitMQ & Redis》的内容有任何疑问、补充或纠错,欢迎在下面的评论系统中留言,与作者一起交流进步,谢谢!(~ ̄▽ ̄)~

评论

发表评论