1.主题中存在多个队列,生产者向主题中指定的队列发送消息
2.在集群模式下,一个消费者集群共同消费一个主题中的多个队列,但一个队列只会被一个消费者消费;在广播模式下,会被订阅主题的所有消费者消费
3.每个消费者组在每个队列上维护一个消费位移(offset),消费者每消费一条消息,会发送一个成功响应,位移就向前移动一次,避免消息重复消费
4.RocketMQ通过一个主题配置多个队列,每个队列维护消费者组的消费位移实现主题模式,提高并发能力
5.一个topic分布多个broker上,一个broker上有多个topic,多对多关系
6.NameServer:broker管理和路由信息管理,去中心化
7.单个broker和每个NameServer连接,发送心跳
8.生产发送消息时,先向NameServer查找Broker注册信息,然后以轮询的方式向队列发送消息
9.消费者消费时,通过NameServer获取Broker注册信息,向 Broker
发送 Pull
请求来获取消息数据
顺序消费
1.普通顺序:一个队列的数据只会被一个消费者消费,因此生产者可以通过hash算法向固定的队列发送消费(例如根据订单的id发送创建,支付),Broker
重启情况下不会保证消息顺序性 (短暂时间)
2.严格顺序:在异常的的情况下也要保证顺序,只要有一台不可用则集群不可用
重复消费
幂等 需要我们业务逻辑来控制,在http的业务中我们都需要做幂等处理
数据库插入,redis key-value来支持
消息堆积
生产者太快,消费者太慢或者消费者出现大量错误
限流降级处理或者增加消费者,大量错误则修改逻辑或者将消息转存到另外个消息队列临时处理
回朔消费
重新消费已经消费过的信息
RocketMQ不会删除已经消费过的信息
RocketMQ支持按照时间回朔消费,时间精确到毫秒
分布式事务(本地事务和存储消息到消息队列才是同一个事务)
常见的解决方式有TCC,2PC,事务消息(half 半消息机制)
RocketMQ采用务消息加上事务反查机制来解决分布式事物
第一步发送half消息时,在事务提交之前,对于消费者来说,这个消息是不可见的
如果是half消息,将原来的主题和队列备份, 将topic主题改为RMQ_SYS_TRANS_HALF_TOPIC
因为消费者未订阅,所以消费者无法消费。RocketMQ开启定时任务,从RMQ_SYS_TRANS_HALF_TOPIC中拉取消息消费,根据生产者组获取一个服务提供者发送事物状态查询请求,根据事物状态来commit/rollback
发送half消息:可以确认broker是否正常;可以用来回查事务状态
回查:执行本地事务,本地事务因网络等原因未返回commit/rollback状态最终导致unknow;本地事务执行成功,发送commit/rollback时,broker异常重启会根据half消息回查。
刷盘机制
同步刷盘:broker存储消息从内存到disk需要ACK返回,适合金融场景
异步刷盘:broker存储消息从内存到disk,通过异步线程处理,异常情况会丢失数据
同步复制:只有消息同步写入主从节点才会返回成功
异步复制:写入主节点就会返回成功
消息的可靠性靠刷盘机制,复制影响可用性。当主节点异常时,因为RocketMQ不支持主从切换,所有消费者只能从slave消费消息,但生产者不能生产消息(单主从情况)
RocketMQ在多主从的情况下,采用Dledger来解决消费顺序问题。Dledger要求写入消息时,要求至少消息复制到半数以上的节点之后,才会给客户端返回成功,并且它支持选举动态切换主节点
存储机制
commitLog:消息主体及元数据存储主体,消息俺顺序写入文件
commitQueue:消息消费的队列,提高数据消费的性能。作为消息消费的索引,存储了commitLog的偏移量(offset),消息大小的size,及tag的hashCode。
indexFile:索引文件,提供了一种可以通过key或时间区间来查询消息的方法
RocketMQ采用混合型存储结构,即broker单个实例下的所有队列共用一个日志文件,提高数据的写入效率。
分布式消息中心
消息丢失的问题:同步落盘
同步落盘速度:使用FileChnnel和DirectBuffer,使用堆外内存,加快内存拷贝;commitLog按顺序写入,数据和索引分离
消息堆积问题:后台定时任务每隔72小时删除没有使用过的旧消息;丢弃消息(参考线程池);消息落库或转移
消息的pull:需要comsumer主动拉取消息
消息的push:实际上是Broker每5s向消费者推送,而comsumer将轮询封装,并注册MessageListener,当消息到达,主动调用consumeMessage()
广播消费与集群消费
1.消息消费的区别:topic中的消息会被订阅的消费者组中一个消费者消费/每个消费者消费
2.消息落盘的区别:集群模式下消费者消费的进度由broker的comsuneQueue保存位移;广播模式下由每个消费者单独自己保存
RocketMQ 不使用 ZooKeeper 作为注册中心的原因,以及自制的 NameServer 优缺点
1.ZooKeeper为了保持一致性,会牺牲可用性;NameServer相互不通信,只为保存组件地址,短时间会出现数据不一致
2.新的服务器加入,由 Producer 定时去请请求NameServer去发现Broker/Consumer自己,不会主动通知
其他
1.使用netty通信自定义协议
2.消息重试负载均衡策略
3.消息过滤器(Producer 发送消息到 Broker,Broker 存储消息信息,Consumer 消费时请求 Broker 端从磁盘文件查询消息文件时,在 Broker 端就使用过滤服务器进行过滤)
4.Broker 同步双写和异步双写中 Master 和 Slave 的交互
5.Broker 在 4.5.0 版本更新中引入了基于 Raft 协议的多副本选举