底层通过Netty实现;
Broker写文件的方式存储消息,消息内容先写到内存中,然后异步刷到磁盘,算盘方式有三种;
异步+内存缓冲池:先写入内存字节缓冲区(writeBuffer) ----> 从内存字节缓冲区(write buffer)提交(commit)到文件通道(fileChannel) ----> 文件通道(fileChannel)定时flush到磁盘
异步:默认,写入映射文件字节缓冲区(mappedByteBuffer) ----> 映射文件字节缓冲区(mappedByteBuffer)定时flush;
同步:发送消息时,消息内容刷到磁盘才会返回;
主从同步HA
- 同步双写 SYNC_MASTER
- 异步复制 ASYNC_MASTER
重试机制(每次重试都会重新进行负载均衡):
Producer:
- 如果是异步发送 那么重试次数只有1次
- 对于同步而言,非超时异常(内部异常)重试两次,超时异常不会重试。
- 如果设置了重试次数,不管是否是同步,是在一个for 循环里去重试,所以它是立即重试而不是隔一段时间去重试。
Consumer:
- 重试的情况:
- 用户返回status为RECONSUME_LATER
- 用户返回null
- 用户业务逻辑处理抛出异常
- 在消息消费失败时,会把该消息回发给Broker,如果回发失败,会重试一次;
- 默认是16次,有一定时间间隔的。它照1S,5S,10S,30S,1M,2M····2H进行重试;
- 消费端消费失败,MQ会将失败的消息添加到重试队列(%RETRY%+consumerGroup),之后的重试,都是通过重试队列来完成的。
- 如果重试16次之后,还未成功,就被放到死性队列(%DLQ%+consumerGroup),后续一般需要人工处理;
说明:Product在异步情况重试失效,而对于Consumer在广播情况下重试失效。
RocketMQ消息消费的长轮询机制
RocketMQ的消费方式都是基于拉模式拉取消息的,长轮询机制的基本设计思路是:消费者如果第一次尝试Pull消息失败(比如:Broker端没有可以消费的消息),并不立即给消费者客户端返回Response的响应,而是先hold住并且挂起请求(将请求保存至pullRequestTable本地缓存变量中),然后Broker端的后台独立线程—PullRequestHoldService会从pullRequestTable本地缓存变量中不断地去取,具体的做法是查询待拉取消息的偏移量是否小于消费队列最大偏移量。如果条件成立则说明有新消息达到Broker端(这里,在RocketMQ的Broker端会有一个后台独立线程—ReputMessageService不停地构建ConsumeQueue/IndexFile数据,同时取出hold住的请求并进行二次处理),则通过重新调用一次业务处理器—PullMessageProcessor的处理请求方法—processRequest()来重新尝试拉取消息(此处,每隔5S重试一次,默认长轮询整体的时间设置为30s)。
RocketMQ消息Pull的长轮询机制的关键在于Broker端的PullRequestHoldService和ReputMessageService两个后台线程。
RocketMQ 事务消息
生产者有三种角色
- NormalProducer(普通)
- OrderProducer(顺序)
- TransactionProducer(事务)
说明:这是在学习阶段做的笔记,看了网友的博客总结的,但是找不到原网页了,如有侵犯,请告知我,我会删除或者附上转载源信息。
来源:oschina
链接:https://my.oschina.net/u/1590092/blog/3144650