消息队列知识点

1、为什么要用消息队列

好处:解耦、异步、削峰;

缺点:系统可用性降低、系统复杂度高、一致性问题。

 

2、Kafka、RabbitMQ、RocketMQ 有什么优缺点?

特性RabbitMQRocketMQKafka
单机吞吐量万级10 万级,支撑高吞吐10 万级,高吞吐,一般配合大数据类的系统来进行实时数据计算、日志采集等场景
topic 数量对吞吐量的影响 topic 可以达到几百/几千的级别,吞吐量会有较小幅度的下降,这是 RocketMQ 的一大优势,在同等机器下,可以支撑大量的 topictopic 从几十到几百个时候,吞吐量会大幅度下降,在同等机器下,Kafka 尽量保证 topic 数量不要过多,如果要支撑大规模的 topic,需要增加更多的机器资源
时效性微秒级,这是 RabbitMQ 的一大特点,延迟最低ms 级延迟在 ms 级以内
可用性高,基于主从架构实现高可用非常高,分布式架构非常高,分布式,一个数据多个副本,少数机器宕机,不会丢失数据,不会导致不可用
消息可靠性基本不丢经过参数优化配置,可以做到 0 丢失同 RocketMQ
功能支持基于 erlang 开发,并发能力很强,性能极好,延时很低MQ 功能较为完善,还是分布式的,扩展性好功能较为简单,主要支持简单的 MQ 功能,在大数据领域的实时计算以及日志采集被大规模使用

 

3、如何保证消息队列的高可用

RabbitMQ高可用:基于主从做高可用性

三种模式:

  • 单机模式:demo级别
  • 普通集群模式(无高可用性):在多台机器上启动多个RabbitMQ实例,一个queue只会放在一个实例上,但每个实例都会同步queue的原数据;这个方案主要是为了提高吞吐量,没有高可用。

说明:这里如果开启消息持久化,消息不一定会丢。

缺点:1、集群内部存在大量数据传输(随机访问实例时要从存储queue的实例拉取数据);2、queue节点宕机,数据就丢失了。

  • 镜像集群模式:每个实例都有queue的全部数据。每次写消息到queue的时候,都会自动把消息同步到多个实例的queue上。

缺点:1、性能开销很大;2、不具有可扩展性。

 

Kafka高可用:

Kafka是分布式消息队列(RabbitMQ不是),一个topic分散在多个机器上,每个机器就放一部分数据。

Kafka的高可用是通过HA机制保证的,就是副本机制。如果某个broker宕机了,这个broker上面的partition在其他机器上都会有副本。如果宕机broker中有leader,可以从其余的replica中进行选举。

写数据时,生产者就写leader,然后将leader数据落到本地磁盘,其他follower从leader来pull数据。follower同步好数据发送ack消息给leader,leader接收到所有follower的ack后(根据选择的模式可调整),就返回成功消息给生产者。

消费数据时,只从leader去读,只有写数据leader接收到所有follower的ack后(根据选择的模式可调整),消息才会被消费者读到。

 

4、如何保证消息不会被重复消费(幂等性)

Kafka中有个offset概念,代表消息的序号,consumer消费了消息之后,会定期把自己消费的消息的offset提交,一旦重启,可以继续从上次提交的offset继续消费。

但是,如果consumer消费消息还没来得及提交offset,就宕机了,还是会发生重复消费。

这时需要根据业务自己来保证:

比如可以基于数据库的主键做幂等;

比如写redis没有问题,因为每次都是set;

比如复杂一点的场景,生成订单,可以写入redis,看是否消费过。

 

5、如何保证消息不丢失

RabbitMQ:

生产者丢失:可以开启confirm模式,给每个消息分配一个唯一的id,每次写入成功后,RabbitMQ会返回ack消息。如果没有处理,会回调nack接口通知消息接收失败。可以结合这个机制在内存中维护消息状态,超过一定时间没收到消息进行重试。

另一种方式是(这种方式十分消耗性能,会降低吞吐量)开启RabbitMQ提供的事务功能,如果发送消息没有被RabbitMQ接收,可以回滚重试,如果接受到了消息可以提交事务。

RabbitMQ丢失:开启持久化。只有持久化到磁盘才会通知生产者ack。

消费端丢失:关闭RabbitMQ的自动ack,在程序中处理完成后手动调用ack。

Kafka:

生产者丢失:设置acks=all。

Kafka丢失:给每个partition至少设置2个副本,至少有一个follower连接,acks=all,retries=MAX。

消费者丢失:关闭自动提交offset。

 

6、如何保证消息的顺序性

RabbitMQ:在consumer内部用内存队列排队;

Kafka:具有相同key的数据都到同一个内存queue,consumer中每个线程消费一个内存queue。

 

7、大量消息在 mq 里积压了几个小时了还没解决

先修复 consumer 的问题,确保其恢复消费速度,然后将现有 consumer 都停掉。

新建一个 topic,partition 是原来的 10 倍,临时建立好原先 10 倍的 queue 数量。

然后写一个临时的分发数据的 consumer 程序,这个程序部署上去消费积压的数据,消费之后不做耗时的处理,直接均匀轮询写入临时建立好的 10 倍数量的 queue。

接着临时征用 10 倍的机器来部署 consumer,每一批 consumer 消费一个临时 queue 的数据。这种做法相当于是临时将 queue 资源和 consumer 资源扩大 10 倍,以正常的 10 倍速度来消费数据。

等快速消费完积压数据之后,得恢复原先部署的架构重新用原先的 consumer 机器来消费消息。

 

8、mq 中的消息过期失效了

RabbitMQ可以设置过期时间,消息积压超过一定时间会被清理。这是需要批量重导,手动查询并导入MQ。

 

9、mq 都快写满了

消费一个丢弃一个,然后使用批量重导的方案补数据。

 

10、如何进行MQ的架构设计

1)支持可伸缩性,参考Kafka的设计,broker->topic->partition。每个partition放一个机器,只存topic的一部分数据,资源不够就增加partition,增加机器,做数据迁移;

2)持久化,落磁盘,并且要顺序写可以减少随机读写的寻址开销;

3)可用性,多副本->leader&follower->broker挂了重新选举leader;

4)数据0丢失。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值