消息队列问题答疑
网关如何接收服务端的秒杀结果
这里只是一个很简单的例子,省去了很多的细节,不同的系统也有不同的设计,思路仅供参考。
网关在收到 APP 的秒杀请求后,直接给消息队列发消息。如果发送消息失败,可以直接给 APP 返回秒杀失败结果,成功发送消息之后,线程就阻塞等待秒杀结果。这里不会无限等待,会设置一个超时事件。等待结束之后,去存放秒杀结果的 Map 中查询是否有返回的秒杀结果,如果有就构建Response,给 APP 返回秒杀结果,如果没有,按秒杀失败处理。
RocketMQ 和 Kafka 的消息模型
现在,假如有一个主题 MyTopic,我们为主题创建 5 个队列,分布到 2 个 Broker 中。有三个生产者Produer0,Produer1 和Producer2。
这三个生产者与2个Broker可以随便对应,也就是说可以轮询发消息,或者说一个生产者的消息全部发送到一个Broker中。
至于消费端,有消费组、消费者和队列这几个概念。
每个消费组就是一份订阅,它要消费主题 MyTopic 下,所有队列的全部消息。这里要注意,消费了的消息并不会从队列中删除,只是从队列中读取了消息。
多个消费组在消费同一个主题时,消费组之间是互不影响的。比如我们有 2 个消费组:G0和 G1。G0 消费了哪些消息,G1 是不知道的,也不用知道。G0 消费过的消息,G1 还可以消费。即使 G0 积压了很多消息,对 G1 来说也没有任何影响。
而一个消费组中可以包含多个消费者的实例。比如说消费组G1,包含了 2 个消费者 C0 和 C1。这里有一个原则,即同一个消费组里面,每个队列只能被一个消费者实例占用。我们可以让消费者 C0 消费 Q0,Q1 和 Q2,C1 消费Q3 和 Q4,如果 C0 宕机了,会触发重新分配,这时候 C1 同时消费全部 5 个队列。
队列占用只是针对消费组内部来说的,对于其他的消费组来说是没有影响的。比如队列 Q2 被消费组 G1 的消费者 C1 占用了,对于消费组 G2 来说,是完全没有影响的,G2 也可以分配它的消费者来占用和消费队列 Q2。