消息队列的思考

什么是消息队列

维基百科的定义:在计算机科学中,消息队列(英语:Message queue)是一种进程间通信或同一进程的不同线程间的通信方式,软件的贮列用来处理一系列的输入,通常是来自用户。消息队列提供了异步的通信协议,每一个贮列中的纪录包含详细说明的数据,包含发生的时间,输入设备的种类,以及特定的输入参数,也就是说:消息的发送者和接收者不需要同时与消息队列交互。消息会保存在队列中,直到接收者取回它。

这定义太复杂了。简单的来讲就是排队系统嘛。这好比,每天到了中午吃饭的点,去麦当劳或者肯德基,都是要排队的嘛,毕竟,员工的数量有限,中午想吃饭的人会很多。大家都会先下单,然后拿着号码去排队取餐。这就是队列啊。

消息队列应用场景

消息队列的应用场景是,当前业务处理量遇到瓶颈,无法及时处理业务,将部分耗时业务分离到消息队列异步处理,避免业务处理失败。
这好比有人在麦当劳点了1个经典套餐,另外一个人点了7个儿童套餐过生日,门店的员工会根据下单情况进行处理,做好经典套餐直接让第一个人来取,肯定不会说,先做完7个儿童套餐再处理第一个任务。

消息队列,可以解耦复杂业务的逻辑,但不可避免,降低了用户的体验。如果每次去麦当劳都需要排对下单,取餐,我想你以后也不大想去他们家吃饭了吧。

优势

队列的好处:
1. 增大的系统的吞吐量,可以处理更多的”请求”。
2. 不管是耗时任务还是即时任务,都可以得到较好的处理。

劣势

队列的劣势:
1. 由于消息队列的存在,任务变成了异步处理,处理完成的时间不可预知。
2. 既然有异步的处理,必然会有数据不一致的情况。

常用的消息队列

RabbitMQ

消息模式

支持消息模式 备注
简单队列 支持单一的消费者
工作队列 支持多个消费者
发布订阅 通过exchange获取队列,消费队列的消息
路由队列 exchange_type='direct' 必须exchange和routing_key匹配才可以消费消费。
主题队列 exchange_type='topic' 可实现队列模糊匹配
RPC 支持RPC调用消费

性能

  1. 根据性能测试第二部分 第一部分 大约在4w个消息每秒,开启ack+持久化后,几乎下降了10倍。该测试在2012年发布的,仅供参考。

实现原理

  1. RabbitMQ是基于AMQP(Advanced Message Queuing Protocol,高级消息队列协议)实现的消息中间件。实现的语言是erlang。
  2. 常用较多的是路由模式。可以实现精确的消息匹配,只需要获取自定义的消息。

PHP支持

  1. 安装Composer包 php-amqplib/php-amqplib
  2. PHP扩展

Kafka

消费模式

暂时只支持一种topics。支持多个消费者,支持分组,可以平均分布消息到不同的分区。

性能

  1. 官方在2014年也做了性能测试。单机达到了80k消息每秒。官方性能测试 文章地址
  2. 可以说是为了性能而存在的消息队列。
  3. Kafka并不保证消息顺序,也不支持数据持久化,部署依赖zookeeper组件实现分布式。

实现原理

Kafka底层是Java实现的。

PHP支持

  1. 优先推荐PHP扩展 rdkafka 主要就基于librdkafka开发的PHP客户端。
  2. 也有相关的Composer包,该包不支持snappy压缩方式的消息。

参考链接

  1. 消息队列及常见消息队列介绍
  2. 消息队列
  3. RabbitMQ和Kafka