引入消息中间件需要关注的问题

参考文章:互联网 Java 工程师进阶知识完全扫盲

I.场景说明(为何要引入)

  1. 解耦
  1. 异步
  1. 削峰

为什么使用消息队列?消息队列有什么优点和缺点?Kafka、ActiveMQ、RabbitMQ、RocketMQ 都有什么优点和缺点?

II.众多消息队列,孰优孰略?(如何选择)

特性ActiveMQRabbitMQRocketMQKafka
单机吞吐量万级万级十万级,支持高吞吐十万级,支持高吞吐
时效性ms级微秒级ms级ms级以内
可用性高可用(基于主从架构)高可用(基于主从架构)高可用 分布式架构高可用,分布式,一个数据多个副本
消息可靠性有较低概率丢失基本不丢参数配置可做到0丢失参数配置可以做到0丢失
功能支持没经过大规模吞吐量场景的验证,社区也不是很活跃基于 erlang 开发,并发能力很强,性能极好,延时很低,开源,比较稳定的支持,活跃度也高;功能较为完善,还是分布式的,扩展性好功能较为简单,主要支持简单的 MQ 功能,在大数据领域的实时计算以及日志采集被大规模使用,社区活跃度很高

综上,各种对比之后,有如下建议:

最早大家都用 ActiveMQ,但是现在确实大家用的不多了,没经过大规模吞吐量场景的验证,社区也不是很活跃;

后来大家开始用 RabbitMQ,但是确实 erlang 语言阻止了大量的 Java 工程师去深入研究和掌控它,对公司而言,几乎处于不可控的状态,但是确实人家是开源的,比较稳定的支持,活跃度也高;

不过现在确实越来越多的公司会去用 RocketMQ,确实很不错,毕竟是阿里出品,但社区可能有突然黄掉的风险(目前 RocketMQ 已捐给 Apache,但 GitHub 上的活跃度其实不算高)对自己公司技术实力有绝对自信的,推荐用 RocketMQ,否则回去老老实实用 RabbitMQ 吧,人家有活跃的开源社区,绝对不会黄。

所以中小型公司,技术实力较为一般,技术挑战不是特别高,用 RabbitMQ 是不错的选择;大型公司,基础架构研发实力较强,用 RocketMQ 是很好的选择。如果是大数据领域的实时计算、日志采集等场景,用 Kafka 是业内标准的,绝对没问题,社区活跃度很高,绝对不会黄,何况几乎是全世界这个领域的事实性规范。

III.引入消息队列可能遇到的问题

  1. 如何保证消息的高可用?

    RabbitMQ 可以开启镜像集群模式,在镜像集群模式下,
    你创建的 queue,无论元数据还是 queue 里的消息都会存在于多个实例上,
    就是说,每个 RabbitMQ 节点都有这个 queue 的一个完整镜像,
    包含 queue 的全部数据的意思。然后每次你写消息到 queue 的时候,
    都会自动把消息同步到多个实例的 queue 上。

    点击查看更多详细解答

  2. 如何保证消息重复消费的问题(幂等性)?

    首先你的明白重复消费会出现什么问题,为什么要保证幂等性。举个例子:
    如果消费者干的事儿是拿一条数据就往数据库里写一条,你可能就把数据在数据库里插入了 2 次,
    那么数据就错了。其实重复消费不可怕,
    可怕的是你没考虑到重复消费之后,怎么保证幂等性。
    解决:
    每个消息加一个全局唯一的序号,根据序号判断这条消息是否处理过,
    然后再根据自己的业务场景进行处理。或更新或丢弃。

    点击查看更多详细解答

  3. 如何处理消息丢失问题(消息的可靠性传输)?
    1. 消息生产者把消息搞丢了:
      RabbitMQ开启 confirm 模式,如果写入了 RabbitMQ 中,RabbitMQ 会给你回传一个 ack 消息,
      告诉你说这个消息 ok 了。
      如果 RabbitMQ 没能处理这个消息,会回调你的一个 nack 接口,告诉你这个消息接收失败,你可以重试。
      而且你可以结合这个机制自己在内存里维护每个消息id的状态,
      如果超过一定时间还没接收到这个消息的回调,那么你可以重发。
    2. MQ自己搞丢了数据:
      RabbitMQ可以开启持久化
    3. 消费端丢失了数据:
      RabbitMQ默认是自动ack的,也就是说消息到了消费端,就会自动确认已经消费了这条消息,
      这时候可能你消费端刚拿到数据,然后挂了,那这条消息不就丢失了。
      关闭RabbitMQ的自动确认,每次消费端逻辑处理完的时候,
      在程序里确认消费完成,通知MQ,这样就保证了在消费端不会丢失了

    点击查看更多详细解答

  4. 如何保证消息的顺序性?
    1. RabbitMQ:
      拆分多个 queue,每个 queue 一个 consumer,就是多一些 queue 而已,确实是麻烦点;
      或者就一个 queue 但是对应一个 consumer
    2. Kafka:
      一个 topic,一个 partition,一个 consumer,内部单线程消费,单线程吞吐量太低,
      一般不会用这个。
      写 N 个内存 queue,具有相同 key 的数据都到同一个内存 queue;然后对于 N 个线程,
      每个线程分别消费一个内存 queue 即可,这样就能保证顺序性。

    点击查看更多详细解答

  5. 如何处理消息积压的问题?消息过期失效问题?

    这种问题出现一般就是消费端出现问题了,导致大量消息积压。
    解决办法:
    修复consumer,恢复其消费能力,然后等待consumer消费完。
    什么?等待太久了?
    消息积压到几百万到上千万数据时,那就有点蛋疼了,确实要好几个小时,那就再提供一种解决方案
    先修复 consumer 的问题,确保其恢复消费速度,然后新建一个 topic,partition 是原来的 10 倍,临时建立好原先 10 倍的 queue 数量。
    然后写一个临时的分发数据的 consumer 程序,这个程序部署上去消费积压的数据,
    消费之后不做耗时的处理,直接均匀轮询写入临时建立好的 10 倍
    数量的 queue。接着临时征用 10 倍的机器来部署consumer,每一批consumer消费一个临时queue的数据。
    这种做法相当于是临时将 queue 资源
    和 consumer 资源扩大 10 倍,以正常的 10倍速度来消费数据。等快速消费完积压数据之后,
    得恢复原先部署的架构,重新用原先的 consumer 机器来消费消息
    如何处理消息过期失效问题
    消息失效这没得办法了呀,只能怪当初设置失效时间的时候没考虑到这个问题了,
    无关紧要的还好,要是重要的类似于订单相关方面的消息,可以写个临时程序,
    根据订单号把丢失的相关消息全查出来,补上。

    点击查看更多详细解答

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值