消息队列和RocketMQ

本文详细介绍了消息队列的作用,如解耦、削峰、异步处理,重点剖析了RocketMQ的架构,包括nameServer、Broker、Consumer和Producer的角色。讨论了RocketMQ的消息模式、消费方式、消息存储结构以及高可用策略,如同步刷盘、异步复制和主从切换。同时,探讨了幂等性、顺序消费和消息丢失问题的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

消息队列&RocketMQ

1. 消息队列的作用、业务场景

解耦:对于一个消息,producer发送给MQ之后,consumer根据需要自己去MQ取消息,而不是consumer直接去调用producer的消息,通过发布/订阅这种模式,就可以实现producer和consumer的解耦。
削峰:对于一些一小段时间的高并发请求,可以交给MQ,然后让这些大量请求慢慢消费,不至于让服务挂掉,这个特别针对数据库,数据库处理并发能力小,可以通过将写请求发送给MQ,然后让MQ到数据库的并发可控,慢慢消费。
异步:consumer去消费producer的一条消息,如果没有MQ,需要调用处理完了才能接着往下让另一个consumer去调用处理,而有了MQ,producer将消息发送给MQ就可以返回了,后续只需要consumer自己去消费MQ消息进行各自的业务处理即可。

2. rocketmq各部件说明

​ nameServer:mq的注册管理中心。保存broker的master、slaver信息,和topic、queue信息。
​ Broker:消息的存储、中转中心。
​ Consumer:消息的消费者。
​ Producer:消息的生产者。

3. Rocketmq的两种消息模式

​ 集群模式:对于订阅同一个topic的consumerGroup,每个consumer消费一部分topic下的消息,所有的consumer合起来完整消费topic的消息。
​ 广播模式:consumerGroup下的每个consumer完整的消费所有topic下的消息。

4. Consumer消费消息的pull和push两种方式

Push方式是服务端接收到消息之后主动推送给客户端,优点:实时性好;缺点:这种主动推送加大了服务端端性能压力,并且客户端接收可能会不稳定。
Pull方式是客户端每隔一段时间向服务端拉取消息消费,优点:减轻了服务端的压力;缺点:每隔一段时间去拉取,实时性不高。

​ 而rocketmq的push方式本质上也是pull(consumer不断轮询从broker拉取消息),是通过长轮询的方式(consumer向broker拉取消息请求,broker会hold住请求一段时间(最长3次5秒),如果中间broker有消息就立刻返回给consumer);rocketmq的pull方式需要开发者自己定义一些参数等。

5. Producer发送消息的不同方式

​ 同步发送:producer.send(msg)。
​ 异步发送:producer.send(msg,callback)。设置回调函数。
​ 延迟发送。
​ 自定义消息发送:messageQueueSelector来控制把消息发送到指定的消息队列。
​ 事务发送:两阶段提交实现事务。

6. nameServer

​ rocketmq的nameServer保存了每个broker和topic信息,并且可以部署多个rocketmq,每个角色都会在每个nameServer中都上报状态信息,可用性高。与broker的连接用netty的tcp连接。

7. 消息存储结构

​ Rocketmq的消息存储是需要落盘的,主要依靠consumerQueue和commitLog配合完成,commitLog是消息的真正物理存储文件,consumerQueue是消息的逻辑队列(类似索引文件),存储的是消息在commitLog的位置。每个topic下的消息队列都有一个consumerQueue(一个topic默认有4个消息队列,也就是4个consumerQueue文件)。在一台borker上commitLog是被所有consumerQueue共享的(不同的topic的consumerQueue也是),所有的消息都存在commitLog文件中(commitLog默认1G,当消息超过1G,会新建一个偏移量接着往下的commitLog文件,然后所有新的消息接着写入)。
​ 这种方式,rocketmq会尽量保证commitLog的顺序写和随机读。对于随机读,会使用页缓存提高读写效率。

8. Broker的高可用

​ 采用master和slave的方式保证高可用,master有读写功能,slave只读。同一组broker,也就是brokername相同,brokerId(0是master,其余都是slave)不同。

9. 同步刷盘和异步刷盘

​ Producer向broker发送消息有两种方式同步刷盘和异步刷盘(broker配置文件修改)。
​ 同步刷盘:broker接收到消息之后立即通知刷盘线程将消息写入磁盘。
​ 异步刷盘:broker接收到消息之后直接返回producer,然后消息存在内存中,积累到一定量才出发刷盘线程进行刷盘。

10. 同步复制和异步复制

​ 对于一组broker,消息需要从master复制到slave,这里有两种同步和异步两种方式(broker配置文件修改)。
​ 同步复制:消息复制到slave之后才返回给客户端。
​ 异步复制:消息到了master之后就返回客户端,一段时间之后才复制给slave。

11. 消息消费的幂等性和重复问题

​ 幂等性的意思是这个消息被多次消费,其结果都是一样的。
​ 处理幂等性和重复消费是一样的思路,主要有两种解决方式:1.在对数据操作之前先判断这个数据的状态。2.维护一个消息表,记录消息的状态,每次消息接收到处理的时候先去表中查看这个消息的状态。

12. 保障顺序消费

​ 对于一些需要特定顺序去消费的功能,需要保证其消费顺序。Rocketmq保证顺序消费需要确保producer发送的消息在同一个消息队列(consumerQueue),通过messageQueueSelector来指定消息存储的队列;并且consumer读消息是单线程的,通过messageListenerOrderly保证单线程(这里单线程是指用messageListenerOrderly会给对应的queue加锁来确保的)。

13. 消息丢失问题

​ 可能由于网络、服务器宕机等情况出现消息丢失的问题,对于producer发送到broker或broker发送到consumer,可以采用二阶段事务的方式(broker\consumer接收到返回一个确认接收到的消息,没有接收到需要回滚事务)。

14. 自己设计一个消息队列

​ 参考rocketmq的实现,以及之前参加的中间件比赛,主要实现broker和nameServer。nameServer可以用zookeeper或etcd来作为注册中心,用来保存broker节点或topic;broker需要考虑较多的点,简单点可以就实现消息队列的put和get方法,需要考虑落盘,顺序写这些,复杂点还要考虑broker的可用性,master\slave等等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值