1.rabbitMQ
1.1 使用RabbitMQ有什么好处?
1、 解耦,系统A在代码中直接调用系统B和系统C的代码,如果将来D系统接入,系统A还需要修改代码,过于麻烦!
2、 异步,将消息写入消息队列,非必要的业务逻辑以异步的方式运行,加快响应速度
3、 削峰,并发量大的时候,所有的请求直接怼到数据库,造成数据库连接异常
1.2 RabbitMQ基本概念
1、 Broker: 简单来说就是消息队列服务器实体
2、 Exchange: 消息交换机,它指定消息按什么规则,路由到哪个队列
3、 Queue: 消息队列载体,每个消息都会被投入到一个或多个队列
4、 Binding: 绑定,它的作用就是把exchange和queue按照路由规则绑定起来
5、 Routing Key: 路由关键字,exchange根据这个关键字进行消息投递
6、 VHost: vhost 可以理解为虚拟 broker ,即 mini-RabbitMQ server。其内部均含有独立的 queue、exchange 和 binding 等,但最最重要的是,其拥有独立的权限系统,可以做到 vhost 范围的用户控制。当然,从 RabbitMQ 的全局角度,vhost 可以作为不同权限隔离的手段(一个典型的例子就是不同的应用可以跑在不同的 vhost 中)。
7、 Producer: 消息生产者,就是投递消息的程序
8、 Consumer: 消息消费者,就是接受消息的程序
9、 Channel: 消息通道,在客户端的每个连接里,可建立多个channel,每个channel代表一个会话任务
由Exchange、Queue、RoutingKey三个才能决定一个从Exchange到Queue的唯一的线路。
1.3 交换器4种类型?
fanout:把所有发送到该交换器的消息路由到所有与该交换器绑定的队列中。
direct:把消息路由到BindingKey和RoutingKey完全匹配的队列中。
topic:
匹配规则:
RoutingKey 为一个 点号'.': 分隔的字符串。 比如: java.xiaoka.show
BindingKey和RoutingKey一样也是点号"."分隔的字符串。
BindingKey可使用 _ 和 # 用于做模糊匹配,_匹配一个单词,#匹配多个或者0个
headers:不依赖路由键匹配规则路由消息。是根据发送消息内容中的headers属性进行匹配。性能差,基本用不到。
1.4 如何避免消息重复投递或重复消费?
在消息生产时,MQ内部针对每条生产者发送的消息生成一个inner-msg-id,作为去重和幂等的依据(消息投递失败并重传),避免重复的消息进入队列;在消息消费时,要求消息体中必须要有一个bizId(对于同一业务全局唯一,如支付ID、订单ID、帖子ID等)作为去重和幂等的依据,避免同一条消息被重复消费。
这个问题针对业务场景来答分以下几点:
1、 拿到这个消息做数据库的insert操作。然后给这个消息做一个唯一主键,那么就算出现重复消费的情况,就会导致主键冲突,避免数据库出现脏数据。
2、 拿到这个消息做Redis的set的操作,因为你无论set几次结果都是一样的,set操作本来就算幂等操作。
3、 如果上面两种情况还不行。准备一个第三方介质,来做消费记录。以Redis为例,给消息分配一个全局id,只要消费过该消息,将<id,message>以K-V形式写入Redis。那消费者开始消费前,先去Redis中查询有没消费记录即可。
1.5 如何确保消息不丢失?
rabbitMQ消息可能丢失的情况:
1.生产者发送方发出消息但没有进入队列。
将信道设置成confirm模式(发送方确认模式),则所有在信道上发布的消息都 会被指派一个唯一的ID。一旦消息被投递到目的队列后,或者肖息被写入磁盘后
(可持久化的消息),信道会发送一个确认给生产者(包念肖息唯一ID )。
2.接收者接到消息,但处理过程出现错误。
当消费者获取消息后,会向RabbitMQ发送回执ACK ,告知消息我被接收。不 过这种回执ACK分两种情况:
自动ACK :消息一旦被接收,消费者自动发送ACK
如果消息不太重要,丢失也没有影响,那么自动ACK会比较方便
手动ACK :消息接收后,不会发送ACK ,需要手动调用
-如果消息非常重要,不容丢失。那么最好在消费完成后手动ACK ,否则接收消息 后就自动ACK , RabbitMQ就会把消息从队列中删除。如果此时f肖费者宕机,那 么消,諷丢失了。
3.队列或者列机。
消息持久化,当然前提是队列和交换机必须持久化
1.6 rabbitmq怎么实现延迟消息队列
使用RabbitMQ来实现延迟任务必须先了解RabbitMQ的两个概念:消息的TTL 和死信Exchange ,通过这两者的组合来实现上述需求。如果队列设置了,消息也 设置了,那么会取小的。所以一个消息如果被路由到不同的队列中,这个消息死亡 的时间有可能不一样(不同的队列设置)O
延迟任务通过消息的TTL和Dead Letter Exchange来实现。我们需要建立2个 队列,一个用于发送消息,一个用于消息过期后的转发目标队列。
生产者输出消息到Queuel,并且这个消息是设置有有效时间的,比如3分钟。 消息会在Queuel中等待3分钟,如果没有消费者收掉的话,它就是被转发到 Queue2 , Queue2有消费者,收到,处理延迟任务。
1.7 如何解决消息队列的延时以及过期失效问题?消息队列满了以后该怎么处理?有几百万消息持续积压几小时,怎么办?
消息积压处理办法:临时紧急扩容:
1、 先修复 consumer 的问题,确保其恢复消费速度,然后将现有 cnosumer 都停掉。
2、 新建一个 topic,partition 是原来的 10 倍,临时建立好原先 10 倍的 queue 数量。
3、 然后写一个临时的分发数据的 consumer 程序,这个程序部署上去消费积压的数据,消费之后不做耗时的处理,直接均匀轮询写入临时建立好的 10 倍数量的 queue。
4、 接着临时征用 10 倍的机器来部署 consumer,每一批 consumer 消费一个临时 queue 的数据。这种做法相当于是临时将 queue 资源和 consumer 资源扩大 10 倍,以正常的 10 倍速度来消费数据。
5、 等快速消费完积压数据之后,得恢复原先部署的架构,重新用原先的 consumer 机器来消费消息。
6、 MQ中消息失效:假设你用的是 RabbitMQ,RabbtiMQ 是可以设置过期时间的,也就是 TTL。如果消息在 queue 中积压超过一定的时间就会被 RabbitMQ 给清理掉,这个数据就没了。那这就是第二个坑了。这就不是说数据会大量积压在 mq 里,而是大量的数据会直接搞丢。我们可以采取一个方案,就是批量重导,这个我们之前线上也有类似的场景干过。就是大量积压的时候,我们当时就直接丢弃数据了,然后等过了高峰期以后,比如大家一起喝咖啡熬夜到晚上12点以后,用户都睡觉了。这个时候我们就开始写程序,将丢失的那批数据,写个临时程序,一点一点的查出来,然后重新灌入 mq 里面去,把白天丢的数据给他补回来。也只能是这样了。假设 1 万个订单积压在 mq 里面,没有处理,其中 1000 个订单都丢了,你只能手动写程序把那 1000 个订单给查出来,手动发到 mq 里去再补一次。
mq消息队列块满了:
如果消息积压在 mq 里,你很长时间都没有处理掉,此时导致 mq 都快写满了,咋办?这个还有别的办法吗?没有,谁让你第一个方案执行的太慢了,你临时写程序,接入数据来消费,消费一个丢弃一个,都不要了,快速消费掉所有的消息。然后走第二个方案,到了晚上再补数据吧。
1.8 message 被可靠持久化的条件是 queue 和 exchange 具有durable 属性,同时 message 具有 persistent 属性才行?
binding 关系可以表示为 exchange -- binding -- queue 。从文档中我们知道,若要求投递的 message 能够不丢失,要求 message 本身设置 persistent 属性,要求 exchange和 queue 都设置 durable 属性。
其实这问题可以这么想,若 exchange 或 queue 未设置durable 属性,则在其 crash 之后就会无法恢复,那么即使 message 设置了 persistent 属性,仍然存在 message 虽然能恢复但却无处容身的问题;同理,若 message 本身未设置persistent 属性,则 message 的持久化更无从谈起。
1.9 RabbitMQ的集群模式有几种?
RabbitMQ 是比较有代表性的,因为是基于主从(非分布式)做高可用性的,我们就以 RabbitMQ 为例子讲解第一种 MQ 的高可用性怎么实现。RabbitMQ 有三种模式:单机模式、普通集群模式、镜像集群模式。
1、 单机模式,就是 Demo 级别的,一般就是你本地启动了玩玩儿的?,没人生产用单机模式
2、 普通模式:以两个节点(rabbit01,rabbit02)为例来进行说明,对于Queue来说,消息实体只存在于其中一个节点rabbit01(或者rabbit02),rabbit01和rabbit02两个节点仅有相同的元数据,即队列结构。当消息进入rabbit01节点的Queue后,consumer从rabbit02节点消费时,RabbitMQ会临时在rabbit01,rabbit02间进行消息传输,把A中的消息实体取出并经过B发送给consumer,所以consumer应尽量连接每一个节点,从中取消息。即对于同一个逻辑队列,要在多个节点建立物理Queue。否则无论consumer连rabbit01或rabbit02,出口总在rabbit01,会产生瓶颈。当rabbit01节点故障后,rabbit02节点无法取到rabbit01节点中还未消费的消息实体。如果做了消息持久化,那么等到rabbit01节点恢复,然后才可被消费。如果没有消息持久化,就会产生消息丢失的现象。
3、 镜像模式:把需要的队列做成镜像队列,存在与多个节点属于RabibitMQ的HA方案,该模式解决了普通模式中的问题,其实质和普通模式不同之处在于,消息体会主动在镜像节点间同步,而不是在客户端取数据时临时拉取,该模式带来的副作用也很明显,除了降低系统性能外,如果镜像队列数量过多,加之大量的消息进入,集群内部的网络带宽将会被这种同步通讯大大消耗掉,所以在对可靠性要求比较高的场合中适用
2.kafka
2.1 概念
高可用,几乎所有相关的开源软件都支持,满足大多数的应用场景,尤其是大数据和流计算领域,
- Kafka高效,可伸缩,消息持久化。支持分区、副本和容错。
- 对批处理和异步处理做了大量的设计,因此Kafka可以得到非常高的性能。
- 每秒处理几十万异步消息消息,如果开启了压缩,最终可以达到每秒处理2000w消息的级别。
- 但是由于是异步的和批处理的,延迟也会高,不适合电商场景。
2.2 什么是kafka
- Producer API:允许应用程序将记录流发布到一个或多个Kafka主题。
- Consumer API:允许应用程序订阅一个或多个主题并处理为其生成的记录流。
- Streams API:允许应用程序充当流处理器,将输入流转换为输出流。
消息 Message
Kafka的数据单元称为消息。可以把消息看成是数据库里的一个"数据行"或一条"记录"。
批次
为了提高效率,消息被分批写入Kafka。提高吞吐量却加大了响应时间。
主题Topic
通过主题进行分类,类似数据库中的表。
分区 Partition
Topic可以被分成若干分区分布于kafka集群中,方便扩容
单个分区内是有序的,partition设置为一才能保证全局有序
副本 Replicas
每个主题被分为若干个分区,每个分区有多个副本。
生产者 Producer
生产者在默认情况下把消息均衡地分布到主题的所有分区上:
- 直接指定消息的分区
- 根据消息的key散列取模得出分区
- 轮询指定分区。
消费者 Comsumer
消费者通过偏移量来区分已经读过的消息,从而消费消息。把每个分区最后读取的消息偏移量保存在Zookeeper 或Kafka上,如果消费者关闭或重启,它的读取状态不会丢失。
消费组 ComsumerGroup
消费组保证每个分区只能被一个消费者使用,避免重复消费。如果群组内一个消费者失效,消费组里的其他消费者可以接管失效消费者的工作再平衡,重新分区。
节点 Broker
连接生产者和消费者,单个broker可以轻松处理数千个分区以及每秒百万级的消息量。
- broker接收来自生产者的消息,为消息设置偏移量,并提交消息到磁盘保存。
- broker为消费者提供服务,响应读取分区的请求,返回已经提交到磁盘上的消息。
集群
每隔分区都有一个首领,当分区被分配给多个broker时,会通过首领进行分区复制。
生产者 Offset
消息写入的时候,每一个分区都有一个offset,即每个分区的最新最大的offset。
消费者 Offset
不同消费组中的消费者可以针对一个分区存储不同的Offset,互不影响。
LogSegment
- 一个分区由多个LogSegment组成,
- 一个LogSegment由.log .index .timeindex组成
- .log追加是顺序写入的,文件名是以文件中第一条message的offset来命名的
- .Index进行日志删除的时候和数据查找的时候可以快速定位。
- .timeStamp则根据时间戳查找对应的偏移量。
2.3 优点和应用场景
优点:
- 高吞吐量:单机每秒处理几十上百万的消息量。即使存储了TB及消息,也保持稳定的性能。
- 零拷贝 减少内核态到用户态的拷贝,磁盘通过sendfile实现DMA 拷贝Socket buffer
- 顺序读写 充分利用磁盘顺序读写的超高性能
- 页缓存mmap,将磁盘文件映射到内存, 用户通过修改内存就能修改磁盘文件。
- 高性能:单节点支持上千个客户端,并保证零停机和零数据丢失。
- 持久化:将消息持久化到磁盘。通过将数据持久化到硬盘以及replication防止数据丢失。
- 分布式系统,易扩展。所有的组件均为分布式的,无需停机即可扩展机器。
- 可靠性 - Kafka是分布式,分区,复制和容错的。
- 客户端状态维护:消息被处理的状态是在Consumer端维护,当失败时能自动平衡。
应用场景:
- 日志收集:用Kafka可以收集各种服务的Log,通过大数据平台进行处理;
- 消息系统:解耦生产者和消费者、缓存消息等;
- 用户活动跟踪:Kafka经常被用来记录Web用户或者App用户的各种活动,如浏览网页、搜索、点击等活动,这些活动信息被各个服务器发布到Kafka的Topic中,然后消费者通过订阅这些Topic来做运营数据的实时的监控分析,也可保存到数据库;
2.4 生产消费基本流程
1.Producer创建时,会创建一个Sender线程并设置为守护线程。
2.生产的消息先经过拦截器->序列化器->分区器,然后将消息缓存在缓冲区。
3.批次发送的条件为:缓冲区数据大小达到batch.size或者linger.ms达到上限。
4.批次发送后,发往指定分区,然后落盘到broker;
- acks=0只要将消息放到缓冲区,就认为消息已经发送完成。
- acks=1表示消息只需要写到主分区即可。在该情形下,如果主分区收到消息确认之后就宕机了,而副本分区还没来得及同步该消息,则该消息丢失。
- acks=all (默认)首领分区会等待所有的ISR副本分区确认记录。该处理保证了只要有一个ISR副本分区存活,消息就不会丢失。
5.如果生产者配置了retrires参数大于0并且未收到确认,那么客户端会对该消息进行重试。
6.落盘到broker成功,返回生产元数据给生产者。
2.5 leader 选举
- Kafka会在Zookeeper上针对每个Topic维护一个称为ISR(in-sync replica)的集合;
- 当集合中副本都跟Leader中的副本同步了之后,kafka才会认为消息已提交;
- 只有这些跟Leader保持同步的Follower才应该被选作新的Leader;
- 假设某个topic有N+1个副本,kafka可以容忍N个服务器不可用,冗余度较低 如果ISR中的副本都丢失了,则:
- 可以等待ISR中的副本任何一个恢复,接着对外提供服务,需要时间等待;
- 从OSR中选出一个副本做Leader副本,此时会造成数据丢失;
副本消息同步
首先,Follower 发送 FETCH 请求给 Leader。接着,Leader 会读取底层日志文件中的消 息数据,再更新它内存中的 Follower 副本的 LEO 值,更新为 FETCH 请求中的 fetchOffset 值。最后,尝试更新分区高水位值。Follower 接收到 FETCH 响应之后,会把消息写入到底层日志,接着更新 LEO 和 HW 值。
相关概念:LEO和HW。
- LEO:即日志末端位移(log end offset),记录了该副本日志中下一条消息的位移值。如果LEO=10,那么表示该副本保存了10条消息,位移值范围是[0, 9]。
- HW:水位值HW(high watermark)即已备份位移。对于同一个副本对象而言,其HW值不会大于LEO值。小于等于HW值的所有消息都被认为是"已备份"的(replicated)。
Rebalance
- 组成员数量发生变化
- 订阅主题数量发生变化
- 订阅主题的分区数发生变化
leader选举完成后,当以上三种情况发生时,Leader根据配置的RangeAssignor开始分配消费方案,即哪个consumer负责消费哪些topic的哪些partition。一旦完成分配,leader会将这个方案封装进SyncGroup请求中发给coordinator,非leader也会发SyncGroup请求,只是内容为空。coordinator接收到分配方案之后会把方案塞进SyncGroup的response中发给各个consumer。这样组内的所有成员就都知道自己应该消费哪些分区了。
分区分配算法 RangeAssignor
- 原理是按照消费者总数和分区总数进行整除运算平均分配给所有的消费者;
- 订阅Topic的消费者按照名称的字典序排序,分均分配,剩下的字典序从前往后分配;
2.6 幂等性
保证在消息重发的时候,消费者不会重复处理。即使在消费者收到重复消息的时候,重复处理,也要保证最终结果的一致性。所谓幂等性,数学概念就是:f(f(x)) = f(x)
添加唯一ID,类似于数据库的主键,用于唯一标记一个消息。
ProducerID:#在每个新的Producer初始化时,会被分配一个唯一的PIDSequenceNumber:#对于每个PID发送数据的每个Topic都对应一个从0开始单调递增的SN值
2.7 如何保证数据不会丢失
- 生产者生产消息可以通过comfirm配置ack=all解决;
- Broker同步过程中leader宕机可以通过配置ISR副本+重试解决;
- 消费者丢失可以关闭自动提交offset功能,系统处理完成时提交offset;
2.8 如何解决积压消费
- 修复consumer,使其具备消费能力,并且扩容N台;
- 写一个分发的程序,将Topic均匀分发到临时Topic中;
- 同时起N台consumer,消费不同的临时Topic;
如何避免消息积压
- 提高消费并行度
- 批量消费
- 减少组件IO的交互次数
- 优先级消费
2.9 如何设计消息队列
需要支持快速水平扩容,broker+partition,partition放不同的机器上,增加机器时将数据根据topic做迁移,分布式需要考虑一致性、可用性、分区容错性
- 一致性:生产者的消息确认、消费者的幂等性、Broker的数据同步;
- 可用性:数据如何保证不丢不重、数据如何持久化、持久化时如何读写;
- 分区容错:采用何种选举机制、如何进行多副本同步;
- 海量数据:如何解决消息积压、海量Topic性能下降;
性能上,可以借鉴时间轮、零拷贝、IO多路复用、顺序读写、压缩批处理。
3.rocketMQ
3.1 RocketMQ由哪些角色组成,每个角色作用和特点是什么?
3.2 RocketMQ Broker中的消息被消费后会立即删除吗?
不会,每条消息都会持久化到CommitLog中,每个Consumer连接到Broker后会维持消费进度信息,当有消息消费后只是当前Consumer的消费进度(CommitLog的offset)更新了。
3.3 消费消息是push还是pull?
RocketMQ没有真正意义的push,都是pull,虽然有push类,但实际底层实现采用的是长轮询机制,即拉取方式
为什么要主动拉取消息而不使用事件监听方式?
事件驱动方式是建立好长连接,由事件(发送数据)的方式来实时推送。
如果broker主动推送消息的话有可能push速度快,消费速度慢的情况,那么就会造成消息在consumer端堆积过多,同时又不能被其他consumer消费的情况。而pull的方式可以根据当前自身情况来pull,不会造成过多的压力而造成瓶颈。所以采取了pull的方式。
3.4 RocketMQ的事务消息是如何实现的?
RocketMQ事务消息的实现机制:
1、半消息机制: 首先发送半消息到消息服务器,如果执行本地事务成功,则提交消息,否则回滚。
2、本地事务执行: 消息发送者在发送半消息后执行本地事务。
3、状态检查: 消息服务器会定期检查半消息的状态。
4、事务回查: 如果消息状态不确定,消息服务器会向发送者回查事务状态,确保消息最终一致性。
3.5 RocketMQ中的消息过滤功能是如何实现的?
RocketMQ消息过滤功能的实现方式:
1、标签过滤: 生产者在发送消息时设置标签,消费者通过指定标签来选择性消费消息。
2、SQL92过滤: 支持基于SQL92标准的过滤表达式,允许在消费端进行更复杂的消息过滤。
3、客户端过滤: 消费者客户端在接收到消息后,可以根据自定义逻辑进行过滤处理。
4、性能优化: 通过过滤减少网络传输的数据量,提高整体性能和效率。
3.6 RocketMQ如何保证消息的可靠传输?
保证RocketMQ消息可靠传输的机制:
1、消息持久化: 所有消息在服务器端被持久化存储,确保不会因服务器故障而丢失。
2、同步双写: 在主备Broker中同步双写消息,提高数据的可靠性。
3、确认机制: 消费者消费消息后,需要向Broker发送确认,未确认的消息会被重新投递。
4、事务消息支持: 提供事务消息机制,保证本地事务和消息发送的原子性。
3.7 rocketMQ和kafka组件的区别
适用场景
Kafka
Kafka最初由LinkedIn开发,主要用于处理大规模的日志数据和实时数据流。它适合以下场景:
日志收集:Kafka可以高效地收集、存储和处理大规模日志数据。
实时数据流处理:Kafka可以与Apache Storm、Apache Flink等实时处理框架结合使用,实现实时数据流的处理和分析。
数据管道:Kafka可以作为不同系统之间的数据管道,实现数据的传输和同步。
RocketMQ
RocketMQ由阿里巴巴开发,主要用于解决分布式系统中的消息传递问题。它适合以下场景:
分布式事务处理:RocketMQ支持分布式事务,适合处理需要保证一致性的业务场景。
消息推送:RocketMQ支持多种消息推送模式,包括集群消费和广播消费,适合需要向多个消费者推送消息的场景。
延迟消息处理:RocketMQ支持延迟消息,适合需要延迟处理的业务场景。
架构设计
Kafka
Kafka采用发布-订阅模式,主要包括生产者、消费者和Broker三个组件。
Broker:Kafka的Broker采用无中心设计,可以水平扩展。多个Broker组成一个Kafka集群,共同承担数据的存储和处理任务。
Topic:Kafka中的数据以Topic为单位进行划分,每个Topic可以有多个Partition。Partition是Kafka实现分布式存储和并行处理的关键。
生产者和消费者:生产者负责向Kafka发送消息,消费者负责从Kafka接收消息并进行处理。生产者和消费者通过Zookeeper进行协调和管理。
RocketMQ
RocketMQ采用主从架构,主要包括生产者、消费者、NameServer和Broker四个组件。
Broker:RocketMQ的Broker分为主Broker和从Broker,主从之间通过同步复制实现数据一致性。多个Broker组成一个RocketMQ集群,共同承担数据的存储和处理任务。
Topic:RocketMQ中的数据同样以Topic为单位进行划分,每个Topic可以有多个Queue。Queue是RocketMQ实现分布式存储和并行处理的关键。
生产者和消费者:生产者负责向RocketMQ发送消息,消费者负责从RocketMQ接收消息并进行处理。生产者和消费者通过NameServer进行协调和管理。
性能
Kafka
Kafka在性能方面具有优势,主要体现在以下几个方面:
数据吞吐量:Kafka具有极高的数据吞吐量,可以达到每秒数百万条消息的处理能力。
延迟:Kafka的延迟较低,可以在毫秒级别内完成消息的传输和处理。
数据类型:Kafka支持多种数据类型,包括文本、二进制数据和JSON等,可以满足不同场景的需求。
RocketMQ
RocketMQ在性能方面同样表现出色,主要体现在以下几个方面:
数据吞吐量:RocketMQ的数据吞吐量同样很高,可以达到每秒数十万条消息的处理能力。
延迟:RocketMQ的延迟也较低,可以在毫秒级别内完成消息的传输和处理。
数据类型:RocketMQ同样支持多种数据类型,包括文本、二进制数据和JSON等。
可靠性
Kafka
Kafka在可靠性方面采取了多种措施:
数据备份:Kafka的每个Partition都有多个副本,可以在一定程度上防止数据丢失。
主从机制:Kafka的Broker之间采用主从复制机制,保证数据的一致性。
高可用性:Kafka的Broker可以水平扩展,通过增加Broker的数量可以提高系统的可用性。此外,Zookeeper作为协调中心,也提高了系统的可靠性。
RocketMQ
RocketMQ在可靠性方面同样采取了多种措施:
数据备份:RocketMQ的每个Queue都有多个副本,可以在一定程度上防止数据丢失。
高可用性:主从Broker之间采用同步复制机制,保证数据的一致性。当主Broker出现故障时,从Broker可以自动切换为主Broker,保证系统的可用性。此外,通过增加Broker的数量也可以提高系统的可用性。NameServer作为协调中心,也提高了系统的可靠性。当某个NameServer出现故障时,其他NameServer可以接管它的任务,保证系统的正常运行。生产者和消费者在发送和接收消息时会自动选择可用的Broker和NameServer进行操作提高了系统的可靠性。生产者和消费者在发送和接收消息时会自动选择可用的Broker和NameServer进行操作避免了单点故障的风险。同时RocketMQ还支持事务消息保证了分布式事务的一致性。
4.mqtt相关
4.1 MQTT是什么?
MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议)是一种轻量级的、基于发布/订阅模式的通讯协议,由IBM的Andy Stanford-Clark和Cirrus Link的Arlen Nipper于1999年设计。它被设计用于有限的带宽和不稳定网络环境中,非常适合物联网(IoT)设备之间的通信。
MQTT协议的主要特点包括:
轻量级:MQTT的消息头部很小,可以减少设备的带宽和功耗,适合在嵌入式设备上使用。
发布/订阅模式:允许一个设备通过发布消息到一个主题,同时多个设备可以订阅这个主题来接收消息。
可靠性:支持三种不同的服务质量(QoS)级别,确保消息的可靠传输。
异步通信:发布者和订阅者不需要同时在线,消息会被存储在服务器上,直到订阅者成功接收。
简单易用:协议简单,易于实现,支持多种编程语言。
MQTT广泛应用于物联网、移动通信、智能家居、智能电网、远程监控和汽车等多个领域。
4.2 它与HTTP有什么不同?
MQTT(Message Queuing Telemetry Transport)协议和HTTP(Hypertext Transfer Protocol)协议都是网络协议,但它们在设计理念、使用场景和性能特点上有着显著的不同:
通信模式:
MQTT基于发布/订阅模式,允许一个设备(发布者)发送消息到主题,而多个设备(订阅者)可以订阅这些主题来接收消息。
HTTP基于请求/响应模式,客户端发送请求到服务器,服务器返回响应。
用途和场景:
MQTT专为物联网(IoT)设计,适用于带宽有限、延迟敏感和不稳定的网络环境,如移动通信、嵌入式设备等。
HTTP主要用于网页浏览、文件传输和API服务,适用于稳定、高带宽的网络环境。
消息大小和开销:
MQTT协议头很小,消息开销低,适合传输小消息。
HTTP协议头相对较大,适合传输较大数据,如文件、图片等。
服务质量(QoS):
MQTT支持三种不同的服务质量级别,可以根据需要选择不同级别的消息传递可靠性。
HTTP没有内建的消息服务质量级别,但可以通过实现特定的错误处理和重试机制来提高可靠性。
连接模型:
MQTT保持长连接,客户端与服务器之间保持持久的会话,直到客户端显式断开连接。
HTTP使用短连接,每个请求完成后连接通常会被关闭,虽然HTTP/1.1支持持久连接(keep-alive),但每次请求/响应交互后,连接可能会处于空闲状态。
实时性:
MQTT设计用于实时通信,延迟低,适合需要即时响应的应用。
HTTP的实时性不如MQTT,尽管有WebSocket等协议可以提供实时通信功能,但HTTP本身更适合非实时应用。
资源消耗:
MQTT由于轻量级设计,对设备资源的要求较低。
HTTP通常需要更多的资源,尤其是在移动或嵌入式设备上。
总的来说,MQTT和HTTP各有优势,适用于不同的应用场景。在选择合适的协议时,需要根据应用的需求、网络环境和设备能力来决定。
4.3 MQTT协议的优点和缺点是什么?
MQTT协议的优点和缺点如下:
优点:
1.轻量级:MQTT协议的设计非常简洁,消息头部很小,这使得它非常适合在带宽有限、计算能力有限的设备上使用,如物联网设备。
2.低延迟:MQTT协议支持实时通信,延迟低,适合需要快速响应的应用场景。
3.支持多种质量服务(QoS)级别:MQTT提供三种不同级别的消息传递可靠性,可以根据应用的需求选择适当的QoS级别。
4.高效的发布/订阅模型:MQTT使用发布/订阅模型,允许一个消息被多个订阅者接收,这减少了网络流量和设备的资源消耗。
5.良好的网络适应性:MQTT协议可以在不稳定或间歇性的网络环境中工作,如移动网络或卫星通信。
6.支持持久会话:MQTT客户端可以与服务器建立持久会话,即使客户端断开连接,服务器也会保存其订阅信息和未接收的消息,直到客户端重新连接。
缺点:
1.安全性问题:虽然MQTT支持加密和认证,但默认情况下,它可能不够安全。需要在传输层使用TLS/SSL或其他安全措施来增强安全性。
2.不适合大量数据传输:MQTT协议不适合传输大量数据,因为它设计用于小型、频繁的消息传递。
3.依赖于中央代理:MQTT使用中央代理(Broker)来处理消息的发布和订阅,这可能导致单点故障和性能瓶颈。
4.实现复杂性:尽管MQTT协议本身简单,但在某些平台上实现客户端和服务端可能需要较多的开发工作。
5.有限的客户端支持:虽然MQTT在物联网设备中广泛使用,但在传统的桌面或移动应用中,HTTP可能是更常见的通信协议。
在选择使用MQTT协议时,需要根据应用的具体需求、网络环境和设备能力来权衡其优缺点。
4.4 MQTT中有哪些消息质量(Qos)等级,并解释它们的含义?
MQTT协议定义了三种消息质量等级(Quality of Service, QoS),用于指定消息传递的可靠性。这些QoS等级如下:
QoS 0 - 至多一次(At Most Once):
这是最低的QoS等级,消息最多被传递一次。
发布者将消息发送给代理(Broker),不会等待任何确认。
如果订阅者在线并能够接收消息,它将收到消息;否则,消息可能会丢失。
这个等级适用于可以容忍消息丢失的场景,例如实时监控或传感器数据,其中最新的数据比旧数据更重要。
QoS 1 - 至少一次(At Least Once):
在这个等级,消息至少被传递一次。
发布者发送消息后,会等待代理的确认(PUBACK)。
如果代理没有收到确认,它会尝试重新发送消息。
订阅者在接收到消息后,需要向代理发送确认(PUBACK)。
这个等级适用于不能容忍消息丢失,但可以容忍重复传递的场景。
QoS 2 - 正好一次(Exactly Once):
这是最高等级的QoS,确保消息精确地被传递一次。
发布者发送消息,并等待代理的确认(PUBREC)。
代理在收到消息后,发送PUBREC给发布者,并等待发布者的响应(PUBREL)。
发布者收到PUBREC后,发送PUBREL给代理。
代理收到PUBREL后,发送最终的确认(PUBCOMP)给发布者。
订阅者在接收到消息后,也需要向代理发送确认(PUBACK)。
这个等级适用于那些需要确保消息不丢失、不重复传递的重要数据,如计费系统或财务交易。
选择合适的QoS等级取决于应用程序的具体需求和网络环境。例如,在稳定的网络环境中,QoS 0可能是足够的,因为它具有最低的延迟和开销。而在不稳定的网络环境中,或者当消息的可靠性非常重要时,QoS 1或QoS 2可能是更好的选择。
4.5 能给出一些使用MQTT的应用场景吗
MQTT(Message Queuing Telemetry Transport)协议由于其轻量级、低延迟和可靠性的特点,被广泛应用于多种物联网(IoT)和移动应用场景。以下是一些典型的MQTT应用场景:
物联网设备通信:
MQTT被广泛用于物联网设备之间的通信,如传感器网络、智能家居设备、工业控制系统等。
它允许这些设备以极低的带宽和功耗发送和接收消息。
移动应用:
MQTT可以用于移动应用的消息推送,例如,即时消息、通知、天气更新等。
它支持断开连接的设备在重新连接时接收离线消息。
智能城市:
在智能城市应用中,MQTT用于连接各种设备和系统,如交通信号灯、监控摄像头、环境监测站等。
它帮助实现实时数据收集和智能决策支持。
远程监控和管理:
MQTT用于远程监控和管理系统,如太阳能发电站、风力发电机组、远程医疗设备等。
它允许实时监控设备状态并远程控制设备。
车辆和运输:
在车联网(V2X)通信中,MQTT可以用于车辆之间的通信,以及车辆与基础设施之间的通信。
它支持实时交通信息交换、车辆诊断数据传输等。
农业:
MQTT在精准农业中用于连接农田传感器、灌溉系统、无人机等,以监控作物生长环境和优化农业管理。
金融服务:
MQTT可以用于金融交易系统、股票市场数据推送、实时汇率更新等金融服务应用。
能源管理:
在智能电网和能源管理系统中,MQTT用于监控能源消耗、控制智能电表和电网设备。
零售和物流:
MQTT可以用于零售和物流行业,用于库存管理、物流跟踪、自动化仓库系统等。
智能家居:
MQTT在智能家居设备中用于控制和监控,如灯光、恒温器、安全系统等。
这些应用场景展示了MQTT协议的多样性和灵活性,使其成为物联网和移动互联网领域的理想选择。