写在文章前面的话:
为啥要写这篇像是技术又不是严肃技术总结的文章呢,主要起因是这样的。我最近新接触消息中间件rabbitmq,而我之前是用过activemq和kafka,虽然消息中间件都是大同小异,但既然要在项目中使用,那就还是需要认真学习一下的。
面对不熟悉的技术组件,我这是这样告诫自己的。新接触的东西不熟悉很正常,可以一时拿没用过来答复自己或他人,但十天半个月之后,如果还以这种姿势示人,就值得好好反省一下了。因为东西不怕新,也不怕不熟悉,就怕你不用心不去主动了解它。要知道,陌生的事物里有令人畏惧的挑战,但同样也有助人成长蜕变的机遇,怎么看怎么想完全取决于我们如何做。
正是抱着这样的想法,我督促自己抓紧时间学习,为此抽时间看了不少相关的技术文章,但看得多了,了解的多了一些,但对于自己不清楚的点,也更加清晰了。但如果真要去系统地输出技术文章的话,我又不知道该如何下手了,总觉得真要写的话,肯定不是一俩小时能够搞定的。但一直在阅读文章,却又不输出的话,我就心痒痒,毕竟感觉走了,下次就不好找了。索性那就用自己口语化的方式,闲谈一下自己最近学习产生的一些认识和想法。
这样相对轻松的方式,并没有严格经过我的考证,所以难免会存在一些错误和偏差,如果哪位读者看出其中的错误,还请不吝赐教,帮忙指出,我将不胜感激。
下面开始我的内容:
rabbitmq 消息中间件,相比kafka,吞吐量差一些,但稳定性明显更高一些,最显著的点,就是rabbitmq支持事务,但这一点处于效率的考虑,好想又很少用。
kafka中的生产者发送消息,直接向指定的topic发送就可以了,消费者们以不同的group加入,就广播的效果,如果属于同一个group,而topic又包括很多partion分区的话,就可以提高并行消费的能力,进而提升吞吐量,这也是kafka吞吐量大的原因之一。
在我看来,不用rabbitmq的事务的话,但相比于kafka,rabbitmq明显就逊色很多了。因为发送消息比较麻烦,不是单纯指定队列名称就可以,而是要指定交换器和routingkey,另外通过交换器和routingkey进行绑定binding到指定的队列上。
如果要是点对点的或是广播的模式,就要创建不同类型的交换器exchange。点对点就用direct类型的exchange,通过指定的routingkey绑定到指定的queue上;如果是广播就用fanout类型的exchange,此时只要将多个queue绑定到这个exchange上(无需指定routingkey),当生产者通过指定exchange发送消息时,所有绑定在exchange上的queue都可以拿到消息了,这样就起到了一个广播的效果。
稳定性保证
rabbitmq生产者在消息发送的时候,有confirm确认机制,在rabbitmq queue收到消息并完成持久化(如果开启持久化的话)会回调对应的方法,告知生产者消息发送成功,如果发送失败的话,也会回调告知异常失败信息,但这点是保证不了的,毕竟如果断电的话,根本是无力回天。
在进行消息发送的时候,可以指定一个消息的唯一id,在消息发送结果告知回调的时候,也可以拿到messageid,如此可以借助该信息完成消息发送的标记及重试等操作。
消费者ack机制
事务
镜像队列
死信队列
消息进入死信队列的时机
1 队列溢出;2 消息过期;3 消息被nack或breject,设置了requeue为true。
延迟队列
如何通过死信队列实现一个延迟任务队列的功能
通过死信队列实现延迟队列有什么弊端和缺点
如何规避这些弊端和缺点
延迟队列的其他实现方式
queue的结构
queue内部数据流动的流程
镜像队列
类似一种主从的关系,也是为了保证消息的可靠性。
如何提升消息处理速度?
批量拉取消息,但随之而来就有ack的问题。
疑问点:
1.消息的prefech设置多个时,消息的ack如何进行,部分成功部分失败时,如何ack?
2.fanout模式的exchange,在进行广播发送的时候,消息是进行复制的方式,发送到了多个queue中吗,那岂不是存在很多重复吗?答:肯定是这样的,毕竟不同的队列,可以对应不同的配置,如果数据只是存一份的话,不是不可以,但那样就要像kafka一样,维护一个类似偏移量的东西,但好像rabbitmq并不是这样处理的,毕竟rabbitmq现在消息就是放在队列里面的,在consumer ack消息之后,就会把消息从队列中清除掉了,所以显然rabbitmq在广播的时候,是使用的复制数据,而不是保留一份,然后走维护偏移量的方式。
网友评论