当autoAck为false的时候,rabbitmq队列会分成两部分,一部分是等待投递给consumer的消息,一部分是已经投递但是没收到确认的消息。如果一直没有收到确认信号,并且consumer已经断开连接,rabbitmq会安排这个消息重新进入队列,投递给原来的消费者或者下一个消费者。
zeromq:不支持,
rocketmq:支持。
消息消费失败的大部分场景下,立即重试99%都会失败,所以rocketmq的策略是在消费失败时定时重试,每次时间间隔相同。
1>发送端的 send 方法本身支持内部重试,重试逻辑如下:
a)至多重试3次;
b)如果发送失败,则轮转到下一个broker;
c)这个方法的总耗时不超过sendMsgTimeout 设置的值,默认 10s,超过时间不在重试。
2>接收端。
Consumer 消费消息失败后,要提供一种重试机制,令消息再消费一次。Consumer 消费消息失败通常可以分为以下两种情况:
由于消息本身的原因,例如反序列化失败,消息数据本身无法处理(例如话费充值,当前消息的手机号被
注销,无法充值)等。定时重试机制,比如过 10s 秒后再重试。
由于依赖的下游应用服务不可用,例如 db 连接不可用,外系统网络不可达等。
即使跳过当前失败的消息,消费其他消息同样也会报错。这种情况可以 sleep 30s,再消费下一条消息,减轻 Broker 重试消息的压力。
activemq:不支持
十七、并发度Kafka:高
一个线程一个消费者,kafka限制消费者的个数要小于等于分区数,如果要提高并行度,可以在消费者中再开启多线程,或者增加consumer实例数量。
rabbitmq:极高
本身是用Erlang语言写的,并发性能高。
可在消费者中开启多线程,最常用的做法是一个channel对应一个消费者,每一个线程把持一个channel,多个线程复用connection的tcp连接,减少性能开销。
当rabbitmq队列拥有多个消费者的时候,队列收到的消息将以轮询的分发方式发送给消费者。每条消息只会发送给订阅列表里的一个消费者,不会重复。
这种方式非常适合扩展,而且是专门为并发程序设计的。
如果某些消费者的任务比较繁重,那么可以设置basicQos限制信道上消费者能保持的最大未确认消息的数量,在达到上限时,rabbitmq不再向这个消费者发送任何消息。
zeromq:高
rocketmq:高
1>rocketmq限制消费者的个数少于等于队列数,但是可以在消费者中再开启多线程,这一点和kafka是一致的,提高并行度的方法相同。
修改消费并行度方法
a) 同一个 ConsumerGroup 下,通过增加 Consumer 实例数量来提高并行度,超过订阅队列数的 Consumer实例无效。
b) 提高单个 Consumer 的消费并行线程,通过修改参数consumeThreadMin、consumeThreadMax
2>同一个网络连接connection,客户端多个线程可以同时发送请求,连接会被复用,减少性能开销。
activemq:高
单个ActiveMQ的接收和消费消息的速度在1万笔/秒(持久化 一般为1-2万, 非持久化 2 万以上),在生产环境中部署10个Activemq就能达到10万笔/秒以上的性能,部署越多的activemq broker 在MQ上latency也就越低,系统吞吐量也就越高。