高级会员
- 威望
- 371
- 贡献
- 478
- 热心值
- 0
- 金币
- 19
- 注册时间
- 2020-3-29
|
1. 你熟悉哪些消息中间件,有什么区别?
• RabbitMQ
○ 万级吞吐量
○ 微秒级,时效性最高
○ 基于主从架构实现高可用 采用镜像模式时 数据量大可能产生性能瓶颈
○ 消息可靠性高
○ 基于 erlang 开发,并发能力很强,性能极好,延时很低
• RocketMQ
○ 10 万级,支撑高吞吐
○ topic 可以达到几百/几千的级别,吞吐量会有较小幅度的下降,这是 RocketMQ 的一大优势,在同等机器下,可以支撑大量的 topic
○ 毫秒级延时
○ 支持分布式架构,可用性高
○ 经过参数优化配置,可以做到 0消息 丢失
○ 底层是用java实现的
• Kafka
○ 10 万级,高吞吐,一般配合大数据类的系统来进行实时数据计算、日志采集等场景
○ topic 从几十到几百个时候,吞吐量会大幅度下降,在同等机器下,Kafka 尽量保证 topic 数量不要过多,如果要支撑大规模的 topic,需要增加更多的机器资源
○ 延迟在 ms 级以内
○ 可用性非常高,分布式,一个数据多个副本,少数机器宕机,不会丢失数据,不会导致不可用
○ 功能较为简单,主要支持简单的 MQ 功能,在大数据领域的实时计算以及日志采集被大规模使用
2. RocketMQ的核心组件?
Rocket 架构主要分为4部分:
• Producer:消息发布者,支持分布式集群部署。Produer 通过 MQ 负载均衡模块选择相应 Broker 中的 queue 进行消息投递,投递过程支持快速失败并且低延迟
• Consumer:消息消费的角色,支持分布式集群方式部署。支持以push推,pull拉两种模式对消息进行消费。同时也支持集群方式和广播方式的消费,它提供实时消息订阅机制,可以满足大多数用户的需求
• Nameserver:NameServer是一个非常简单的Topic路由注册中心,其角色类似Dubbo中的zookeeper,支持Broker的动态注册与发现。主要包括两个功能:Broker管理,NameServer接受Broker集群的注册信息并且保存下来作为路由信息的基本数据。然后提供心跳检测机制,检查Broker是否还存活;路由信息管理,每个NameServer将保存关于Broker集群的整个路由信息和用于客户端查询的队列信息。然后Producer和Conumser通过NameServer就可以知道整个Broker集群的路由信息,从而进行消息的投递和消费。NameServer通常也是集群的方式部署,各实例间相互不进行信息通讯。Broker是向每一台NameServer注册自己的路由信息,所以每一个NameServer实例上面都保存一份完整的路由信息。当某个NameServer因某种原因下线了,Broker仍然可以向其它NameServer同步其路由信息,Producer,Consumer仍然可以动态感知Broker的路由的信息。
• Broker:主要负责消息的存储、投递和查询以及服务高可用保证,为了实现这些功能,Broker包含了以下几个重要子模块
○ Remoting Module:整个Broker的实体,负责处理来自clients端的请求。
○ Client Manager:负责管理客户端(Producer/Consumer)和维护Consumer的Topic订阅信息
○ Store Service:提供方便简单的API接口处理消息存储到物理硬盘和查询功能。
○ HA Service:高可用服务,提供Master Broker 和 Slave Broker之间的数据同步功能。
○ Index Service:根据特定的Message key对投递到Broker的消息进行索引服务,以提供消息的快速查询。
3. 什么情况下会出现消息重复?
• 发送时消息重复:当一条消息已被成功发送到服务端并完成持久化,此时出现了网络闪断或者客户端宕机,导致服务端对客户端应答失败。 如果此时生产者意识到消息发送失败并尝试再次发送消息,消费者后续会收到两条内容相同并且 Message ID 也相同的消息。
• 投递时消息重复:消息消费的场景下,消息已投递到消费者并完成业务处理,当客户端给服务端反馈应答的时候网络闪断。 为了保证消息至少被消费一次,消息队列 RocketMQ 的服务端将在网络恢复后再次尝试投递之前已被处理过的消息,消费者后续会收到两条内容相同并且 Message ID 也相同的消息。
• 负载均衡时消息重复(包括但不限于网络抖动、Broker 重启以及订阅方应用重启):当消息队列 RocketMQ 的 Broker 或客户端重启、扩容或缩容时,会触发 Rebalance,此时消费者可能会收到重复消息。
4. 什么是幂等性?
就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用
5. 如何确保消息不会被重复消费(幂等性)?
• 消费端处理消息的业务逻辑保持幂等性:原理是只要第二三四条消息执行时对项目不会造成影响,那么就不需要去管它
• 保证每条消息都有唯一编号且保证消息处理成功与去重表的日志同时出现:原理是利用一张日志表来记录已经处理成功的消息ID,如果新来的消息ID已经在日志表中,那么就不再处理这条消息
• RocketMQ不保证消息不重复,重复时如果由消息系统来处理会对消息系统的吞吐量和高可用有影响,所以需要在业务的进行消息去重操作。
6. RocketMQ如何保证消息不丢失(可靠性)?
• producer到broker
○ 采用同步发送
○ 配置发送重试策略
• broker端消息可靠性
○ 消息落盘持久化
○ 同步刷盘,可以保证数据绝对安全,但是吞吐量不大
○ 异步刷盘(默认):这种方式吞吐量大,性能高,但是 PageCache中的数据可能丢失,不能保证数据绝对的安全。
• consumer端消息可靠性
○ 消费重试:消费者从RocketMQ拉取到消息之后,需要返回消费成功来表示业务方正常消费完成。因此只有返回CONSUME_SUCCESS才算消费完成,如果返回CONSUME_LATER则会按照不同的messageDelayLevel时间进行再次消费,之后再次进行消费重试,如果消费满16次之后还是未能消费成功,则不再重试,会将消息发送到死信队列,从而保证消息存储的可靠性。
○ 死信队列:未能成功消费的消息,消息队列并不会立刻将消息丢弃,而是将消息发送到死信队列,如果消息最终进入了死信队列,则可以通过RocketMQ提供的相关接口从死信队列获取到相应的消息,保证了消息消费的可靠性。
7. rocketmq的事务消息的架构设计
• 1. 生产者执行本地事务,修改订单支付状态,并且提交事务
• 2. 生产者发送事务消息到broker上,消息发送到broker上在没有确认之前,消息对于consumer是不可见状态
• 3. 生产者确认事务消息,使得发送到broker上的事务消息对于消费者可见
• 4. 消费者获取到消息进行消费,消费完之后执行ack进行确认
• 5. 这里可能会存在一个问题,生产者本地事务成功后,发送事务确认消息到broker上失败了怎么办?这个时候意味着消费者无法正常消费到这个消息。所以RocketMQ提供了消息回查机制,如果事务消息一直处于中间状态,broker会发起重试去查询broker上这个事务的处理状态。一旦发现事务处理成功,则把当前这条消息设置为可见
8. MQ如何解决消息积压?
• producer生产速率过快:此时需要可以采取的方式包括生产者限流紧急情况可以采用生产者熔断,消费者扩容的方式解决
• producer消息发送速率等于consumer消息的消费速度:对RocketMQ 进行扩容,提高消息堆积能力
9. 如何保证消息的顺序性?
我们往一个topic里面发送消息时,它默认会维护几个队列,是随机发送到这些队列里面的。消费者集群消费时,实际上是一个服务监听一个队列。我们发送消息时,对于同个数据的操作指定发送到一个队列就好了,这时消费者就是按照顺序来消费的。
10. 如果不用MQ,用异步的方式行吗?
不行,异步的方式虽然能提升响应速度,但是不能像MQ一样兼顾实现系统解耦
|
|