Round-robin dispatching

默认情况下,RabbitMQ按顺序分发消息给下一个消费者。平均每个消费者会得到相同数量的消息。

Message acknowledgment

为了确保消息不丢失,RabbitMQ支持消息确认。消费者通过发送确认来告诉RabbitMQ已经收到消息,并且已经处理完成,而且RabbitMQ可以删除它了。

如果一个消费者在发确认之前就已经死了,那么RabbitMQ认为消息没有被处理完,并且会将它重新加入队列中。这个时候如果有另一个消费者在线的话,将把这个消息重新投递给另一个消费者。用这种方式可以确保消息不丢失。

一个常见的错误是忘记确认,这样后果会很严重。这种情况下,客户端退出的时候消息会重新投递,这样的话,RabbitMQ需要消耗更多的内存,因为它不能释放这些没有被确认的消息。

Message durability

我们已经学习了怎样确保即使消费者死了消息也不丢失。但是,如果RabbitMQ服务器停止了,消息仍然会丢失。

当RabbitMQ服务器退出或者宕机的时候,它将忘记队列和消息。为了确保消息不被丢失,有两件事情是必须的:队列和消息都要持久化。

首先,我们需要确保RabbitMQ从来不会丢失队列。为此,我们需要这样做:

Work Queues-LMLPHP

这段代码没写错,但问题是已经有一个队列叫"hello"了,并且没有被持久化。RabbitMQ不允许你用不同的参数重新定义一个已经存在的队列。

消息持久化是通过MessageProperties的值设为PERSISTENT_TEXT_PLAIN来做的

Work Queues-LMLPHP

注意:

  标记消息为持久化并不能完全保证消息不会丢失。即使,我们告诉RabbitMQ要将消息保存到磁盘上,但是在window上仍然有一段很短的时间,当RabbitMQ接受了消息但还没来得及保存。RabbitMQ不会对每一条消息做fsync(2),它可能只是保存在缓存里面而没有真的保存到磁盘上。这种持久化不够健壮,但对于一些简单的任务来说是足够了。如果需要更强壮的保证,你可以使用publisher confirms(发布确认)

Fair dispatch

你可能已经注意到,消息分发并不是按照我们想的那样进行的。RabbitMQ只是将第n条消息发给第n个消费者。为了改变这种默认的行为,可以用basicQos方法将prefetchCount设为1。这将告诉RabbitMQ一次给出的消息不能超过1条。换句话说,这样的话RabbitMQ不会分发一个消息直到这个消费者已经处理完成并确认了前一条消息。代替,它会将消息分发给下一个空闲的消费者。

Work Queues-LMLPHP

小结:

1、为了保证即使消费者死了消息也不会丢失,需要消费者手动确认

2、为了保证即使即使RabbitMQ服务器宕机了消息也不丢失,需要持久化消息的队列。但这种方式也不能完全保证消息不丢失,因为有可能RabbitMQ并不是每收到一条消息就做一次fsync(2)操作,也许只是将消息保存在缓存中,这个时候如果宕机,则消息会丢失。

3、为了更进一步的保证即使服务器宕机了也不丢消息,需要发布消息的时候也予以确认

4、发布消息确认+队列、消息持久化+消费消息确认

5、默认情况下,RabbitMQ分发消息的时候不管消费者有没有确认之前的消息,不管发给消费者的消息有多少没有确认,反正收到一个消息就发一个。这就可能造成有的消费者很忙,有的很闲。为了避免这个问题,可以将basicQos都设为1,这样就可以兼顾到消费者处理的情况了。

Work Queues-LMLPHP

Work Queues-LMLPHP

参考  http://www.rabbitmq.com/tutorials/tutorial-two-java.html

05-11 19:26