1、消息队列的作用及对比
消息队列主要用到的为rabbitMQ,RocketMQ以及kafka,其中rabbitMQ是用erlang编写的比较稳定的MQ,但是不容易深入去掌握;RocketMQ是阿里出品的稳定MQ,但是目前社区不活跃;kafka主要用于大数据领域以及记录日志,可用性非常高。
2、消息队列的作用
缺点:降低了系统的可用性,提高了系统的复杂性,以及存在信息一致性的问题。
3、如何保证消息队列的可用性
本质为传统的消息队列。
通过镜像集群模式,每个MQ的节点都对所有的queue数据进行备份同步。
缺点:性能开销大,没法线性扩展。
天然的分布式消息队列。
0.8版本以后,集群维护一个主从模式,每组partition会选出一个节点作为leader,每次外界的读写操作都只能与leader节点对接,然后再同步到所有的节点。如果leader节点挂了,followers会重新选出一个leader节点。
4、如何保证消息队列不会重复消费
Kafka有个offset作为消息的序号,每次consumer消费了数据之后,每隔一段时间会将offset提交表示已经消费过了。但如果这是系统kill进程重启,会使得consumer来不及提交offset,重启后就会造成重复消费。
一个数据,或者一个请求,给你重复来多次,你得确保对应的数据是不会改变的,不能出错。
比如数据库加主键或者唯一索引;
或者利用一条全局id,如订单id,每次要消费时去redis里查一下,没有就消费,有则不处理。
5、如何保证消息队列不会丢失消息
生产者端:
1、开启事务模式,同步操作,提交一个操作会阻塞在那,传输失败则回滚,会造成资源极大的消耗。
2、开启confirm模式,异步操作,每次写消息会分配一个唯一的id,如果传输成功,MQ会回复一个ack消息,如果失败会回复传输失败。
MQ端:
设置持久化,要将queue和消息都持久化。
消费者端:
关闭自动ack机制,在消费者处理完后自行发送ack给MQ。
消费者端:
关闭自动offset机制,在消费者处理完后自行发送offset给kafka。
Kafka端:
当某个leader挂了时,需要重新选举leader,此时会丢失一些数据未同步。
此时需要通过参数设置,让leader与followers保持联系,确保partitions存在副本等,保证leader切换时不会发生数据丢失。
生产者端:
设置ack=all,即你的 leader 接收到消息,所有的 follower 都同步到了消息之后,才认为本次写成功了,否则无限重试,则一定不会丢失数据。
6、如何保证消息队列顺序性
一个queue对应一个consumer,consumer内部用内存队列做排队。
每个key对应一个内存队列,保证顺序性。
7、消息队列消费端出问题如何解决
如果消费端如MySQL挂了,会有很多消息积压在mq中,此时应该先修复消费端的问题,然后进行临时扩容去快速消费mq中的消息。
在低峰期手动将消息找出来重新消费。
写临时程序来丢弃消息,再在低峰期时手动将消息找回来重新消费。
8、如何自行设计一个消息队列