RocketMQ

1.RocketMq架构分析

Topic图解:

消费方式:

 消息特点:

 Request-reply,相当于dubbo底层RPC协议,可以携带producer的requestId,消费端返回响应的时候返回requestId,这样就使用MQ消息队列实现了RPC调用。

顺序:

局部有序:Producer为一个,并且控制好Producer顺序,将局部消息,有序的发送到一个queue中,这样就可以保证局部有序(一个queue内)。

全局有序:只能有一个producer,一个queue

NameServer注册机制:

 消息粒度划分:topic+broker+queueId

updatetopic -c DefaultCluster -n nameserver:port -t

此条命令的意思是复制所有toipc节点到nameServer下。 

 updatetopic -b broker:port -t:此命令为在broker下创建topic,并注册到nameServer下

 第一组数据为消费端拿到的所有queue有6条(消费端只会关注topic,只要是queue中有数据,不管是哪个nameserver下的broker下的queue,都会消费,除非指定),因为命令创建topic-->"wula"的时候指定了-w2 -r2,正常情况下为8条队列,但是broker1只注册到了nameServer2上,未注册到nameServer1,所以broker2上的queue(-R)只有2个。但是broker2在nameServer1和2都注册了,所以又6条queue

读写队列不一致会怎样

W为WriteQueue,R为ReadQueue

 如果发现写队列较多,想要缩小时,如果同时去除W和R,会导致消息丢失,可以先缩小W,等W对应的R消费完成之后,再缩小R,这叫做热变更。

重试队列、死信队列

public class MessageListenerImpl implements MessageListener {
	@Override
	public Action consume(Message message, ConsumeContext context) {
		//处理消息
		doConsumeMessage(message);
		//方式1:返回 Action.ReconsumeLater,消息将重试
		return Action.ReconsumeLater;
		//方式2:返回 null,消息将重试
		return null;
		//方式3:直接抛出异常, 消息将重试
		throw new RuntimeException("Consumer Message exceotion");
	}
}

 在消费端,如果是ConcurrentListener,那么如果消息消费失败产生异常后,可以返回RESUME_LATER,如果返回此状态,消费者产生RETTRY_QUEUE,生产者获取重试队列中的消息重新投递。messageDelayLevel为重新消费消息的延迟时间,如第一次为1S,第二次重复消费的时间为5S,第三次重新消费的时间为10S,当重复消费次数到达MaxReconsume重复消费的最大次数,那么就会将消息放入死信队列DLQ,然后由人工处理。

RocketMQ默认允许每条消息最多重试16次,如果设置为20次,那么在重试16次后,消息重试间隔为2h

Kafka是需要客户自己维护重试队列和死信队列。

有序消息

生产者保证有序性

producer一定要同步发送,一个线程工作,如果是异步发送,多个线程发送,是无法保证有序的。

 消费者

 

 type=queue.size%3;

当Type为0时,消费者处理Type为0的线程都是同一个线程Thread_3

当Type为1时,消费者处理Type为1的线程都是同一个线程Thread_1

当Type为2时,消费者处理Type为2的线程都是同一个线程Thread_2

这样就保证了消费者消费消息的顺序性

延迟消息

 消费的时候,每条消息根据 入参%18(延迟级别),这样就可以在一个Topic下根据不同的参数实现不同的消费级别。

事务

分布式思想:2段提交,回调检查,重试来保证了最终一致性

 假如service挂了,那么就不能保证MQ的commit和rollback一定会发送出去,所以MQ使用的是回调检查机制。此数据库要保证和Service不是同一个服务,数据要在producer生成的时候插入。

consumer能否看到producer推送的消息,取决于A操作(调用接口和更新mysql)的成功与否。 如果本地事务的状态是失败的,那么producer就会发出rolback的消息给MQ,MQ就会回滚这个消息,不让消费者消费到。如果本地事务是成功的,那么producer就会发出commit给MQ,那么这条消息就可以被消费者消费。

 

 

 代码实现

 

为什么要使用RocketMq?

源码解析

源码层次

                                                                         

客户端设计风格

 根据不同的Code选择不同的线程池,资源隔离,偏微服务

为什么RocketMq和Kafka性能好?

mmap实现零拷贝

传统IO:read() + write()

1.用户进程通过read()方法向系统发起调用,上下文从用户态转换为内核态
2.DMA控制器把数据从硬盘中拷贝到内核读缓冲区
3.CPU将内核缓存区的数据拷贝到用户缓冲区
4.内核态转换为用户态,read()方法执行完毕
5.用户进程通过write()方法向系统发起调用,上下文又从用户态转换为内核态
6.CPU将用户缓冲区的数据拷贝到socket缓冲区/内核写缓冲区
7.DMA控制器将socket缓冲区/内核写缓冲区的数据拷贝到网卡
8.内核态转换为用户态,write()方法执行完毕

2次DMA复制,2次CPU复制,4次用户态、内核态的互相切换

mmap实现零拷贝:mmap主要实现方式是将内核读缓冲区的地址和用户缓冲区的地址进行映射,内核缓冲区和用户缓冲区共享,从而减少了从读缓冲区到用户缓冲区的一次CPU拷贝

1.用户进程通过mmap()方法向系统发起调用,上下文从用户态转换为内核态
2.DMA控制器把数据从硬盘中拷贝到内核读缓冲区
3.内核态转换为用户态,mmap()方法执行完毕
4.用户进程通过write()方法向系统发起调用,上下文又从用户态转换为内核态
5.CPU将用户缓冲区的数据拷贝到socket缓冲区/内核写缓冲区
6.DMA控制器将socket缓冲区/内核写缓冲区的数据拷贝到网卡
7.内核态转换为用户态,write()方法执行完毕


2次DMA复制,1次CPU复制,4次用户态、内核态的切换

引入Page Cache

PageCache机制,页缓存机制,是OS对文件的缓存机制,用于加速对文件的读写操作。
一般来 说,程序对文件进行顺序读写的速度几乎接近于内存读写速度,主要原因是由于OS使用 PageCache机制对读写访问操作进行性能优化,将一部分的内存用作PageCache。

顺序读写为什么快?

它是一种将磁盘块预读到page cache的机制。

Linux内核中文件预读算法的具体过程是这样的:对于每个文件的第一个读请求,系统读入所请求的页面并读入紧随其后的少数几个页面(不少于一个页面,通常是三个页面),这时的预读称为同步预读。对于第二次读请求,如果所读页面不在Cache中,即不在前次预读的group中,则表明文件访问不是顺序访问,系统继续采用同步预读;如果所读页面在Cache中,则表明前次预读命中,操作系统把预读group扩大一倍,并让底层文件系统读入group中剩下尚不在Cache中的文件数据块,这时的预读称为异步预读。

以顺序读为例,当用户发起一个 fileChannel.read(4kb) 之后,实际发生了两件事

  1. 操作系统从磁盘加载了 16kb 进入 PageCache,这被称为预读
  2. 操作通从 PageCache 拷贝 4kb 进入用户内存

最终我们在用户内存访问到了 4kb,为什么顺序读快?很容量想到,当用户继续访问接下来的 [4kb,16kb] 的磁盘内容时,便是直接从 PageCache 去访问了。试想一下,当需要访问 16kb 的磁盘内容时,是发生 4 次磁盘 IO 快,还是发生 1 次磁盘 IO+4 次内存 IO 快呢?答案是显而易见的,这一切都是 PageCache 带来的优化。

topic、group、tag关系

同一个group下,消费者1有tag1,消费者2有tag1或tag2,那么这样就会导致tag2失效。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值