消息中间件常见问题

人走茶凉 提交于 2019-12-01 02:55:11

高可用,重复消费,幂等,可靠性传输,消息丢失

1、 kafka,rabbitMQ,activemq,rocketMQ使用场景及区别技术选型
吞吐量、topic数量对吞吐量的影响、时效性、可用性、可靠性、核心特点、优劣势总结
activemq:吞吐量万级 非常成熟,功能比较强大,大量的公司再项目中有应用 偶尔会有低概消息丢失,近些年应用越来越少 官方社区维护越来越少,而且确实主要基于解耦和异步来用的,较少在大规模吞吐的场景下使用
rabbitMQ: 吞吐量万级 跟服务器有关系 基于erlang开发,性能较好 延时低,而且提供开源的管理界面 社区比较活跃,近些年互联网公司用rabbitmq的比较多,因为基于erlang语言 不懂源码,比较难进行定制和掌控;
rocketMQ:单机吞吐量10w,topic可以达到几百或者上千级别 topic越多吞吐量会有较小幅度的下降,阿里大规模使用,比较可靠、日处理消息上百亿、拓展方便、社区维护可以,只会复杂MQ业务场景
kafka:功能简单,主要支持简单的mq功能,ms级延迟 极高的可用性和可靠性不过有消息重复消费 在大数据领域的实时计算以及日志采集被大规模使用。

中小型公司:rabbitMQ,技术实力一般 挑战不是很高 社区比较活跃;
大型公司:rocketMQ 基础架构研发实力较强
如果是大数据领域的实时计算、日志采集等场景 用kafka是业内标准的,社区活跃度比较高,绝对不会黄,更何况是全世界这个领域的实时性规范;


2. 消息队列的使用场景,为什么使用消息队列
系统之间解耦 通过发布订阅模型 不同系统之间进行解耦,比如B系统以来A系统中某一消息,A系统只用负责往消息队列中发送消息,B只管消费,如果新增C,D等消费者A不用关注;
削峰 当系统A突然有大量数据,如果通过A系统RPC进行调用入库,A系统很可能将系统打挂,因此可以通过MQ进行削峰,然后由A系统慢慢消费;
异步 比如:A需要向C,D,E,F等多个系统依赖A系统中某一个消息或者通知,可以通过消息队列的方式,不需要同步调用rpc方式进行调用;

缺点:增加系统复杂性,如果MQ挂了整个系统都会挂掉,MQ引起的问题(消息丢失,消息顺序性,消息重复发送 无法保证消息)

3、RabbitMQ的高可用和kafka的考可用
不是分布式的,是集群
三种模式:单机模式、集群模式和镜像模式
集群模式:在多台机器上启动多个rabbitmq实例,每个机器启动一个。但是你创建的queue,只会放到一个rabbitmq实例上,但是每个实例都同步queue的元数据;待消费的时候 实际上如果连接到了另外一个实例
那么那个实例会从queue所在实例上拉取数据过来。 因此 这种模式模式不可靠,如果存储数据的queue所在实例挂了数据就丢失了,另外如果数据量太大 两个实例之间传输数据量太大;
镜像集群模式:高可用模式,每个节点上都有这个queue的一个完整镜像(元数据和消息内容),然后每次写消息到queue的时候,都会自动把消息同步到多个实例的queue里面;
缺点:性能开销太大,消息需要同步到所有机器上,导致网络带宽 增加机器负载 没有办法线性扩展queue;
开启方式:从管理控制台 新增策略 (镜像集群模式)同时可以指定 要求数据同步到所有节点 或者同步到指定数量的节点,再次创建queue时候 会使用该策略;

不是分布式的:意思是数据在单个集群节点上完整存储
kafka分布式
broker进程就是kafka在每台机器上启动的自己的一个进程,也可以认为是kafka集群中的一个节点;
kafka由多个broker组成 每个broker是一个节点; 创建topic 该topic可以划分到多个partition,每个分区可以存在于不同的broker上,每个partition就存放一部分数据;
kafka是天然的分布式消息队列 也就是一个topic数据可以存储到多个partition 每个partition可以分布在不同的broker上;

实际上rabbitmq 之类的并不是分布式消息队列,他就是传统的消息队列 只不过提供了一些集群、HA的机制而已,因为无论怎么玩,rabbitMQ中的一个queue的数据都是放到一个节点下;
在镜像集群下 也就是每个节点都存放了这个queue的完整数据;

HA机制:高可用机制 kafka通过副本机制 partition存在多个副本 副本中会选举leader 其它的副本为fllower,写入数据写入到leader同步数据会同步到fllower中,客户端连接连接到leader;
此时:一旦某一台机器宕机了,如果是leader没有了,但是此时别的机器上还有fllower此时kafka会自动感知到leader死了,会将其它fllower进行选举为leader节点;


4. 消息的重发,补充策略,如何保证消息不会被重复消费(如何保证幂等性)
rabbitMQ、rocketMQ、kafka等消息中间件都会出现消费者重复消费消息的问题,因为这个保证不应该是mq保证的,是消费端自己保证;
kafka重复消费:kafka上有一个offset的概念,就是每一个消息写进去都会有一个offset,代表它的序号 然后消费者消费数据之后
原因:每隔一段时间会把自己消费过的消息的offset进行提交,代表已经消费过了; 基于zookeeper实现的,zk里面就记录了消费者当前消费到offset的位置;
消费者不是消费完一条数据就立马提交offset的,而是定时定期提交一次offset的; 如果客户端挂了或者重启了 导致offset未能及时提交 则再次进行消费时候会从上次开始消费的地方重复消费;
解决方式(保证幂等):结合业务
1)拿到数据进行写库,可以根据相应主键或者联合主键进行保证,或者数据来了先查下数据库(注意主从库)建议查询主库进行过滤或者进行更新;
2)通过缓存标识或者分布式锁 当然如果直接写到redis中的set里面就没有问题,毕竟是天然幂等;
3)复杂点的场景是 消息里面增加全局唯一标识,收到消息后先去redis里面进行查找,如果没查到则进行消费然后记录到redis中


????如果多个消费者是怎么处理的?在rabbitmq中是怎么处理的?

5. MQ 系统的数据如何保证不不丢失,就是数据一条不能多一条不能少
丢失原因:生产者过程中消息没有写到mq中、mq自己丢失、或者消费者在消费过程中丢失;
rabbitMQ: 消息没有传输到rabbitmq中 就丢失了,或者rabbitmq中已经接收到消息但是还没有来得及保存就出现问题了或者已经保存到内存但是没有序列化到硬盘 ,消费者消费到了消息但是还没有来得及处理就挂掉了 rabbitmq以为消费者已经消费成功了;
解决方式:
生产者可以开启一个事务(会引起阻塞会使吞吐量下降)或者异步确认;
第一步创建queue设置其为持久化 保证rabbitmq中queue的元数据会序列化;第二部:发送消息时候将消息体设置为持久化即deliveyMode=2,来保证消息的持久化;
同时持久化机制跟生产者的confirm机制配合起来,保证只有消息体持久化????(这个是保存到内存还是保存到硬盘,如果保存到内存还会丢失 无法完全避免)完成后 才会通知生产者;
消费端关闭自动确认回复autoAck机制
kafka:
生产者:写入失败,设置重试次数 如果超过n次进行人工干预;如果设置为max
服务端丢失:在分区中的副本同步过程中,如果副本的leader刚收到生产者消息并且自己已经保存下来准备同步给副本时候 挂掉
解决方式:每个partition至少要有两个副本 并且至少有一个副本始终跟leader保持连接 同时在生产者设置acks=all,要求写入到所有副本 才算写入成功;
消费端丢数据:消费到了消息,消费者自动提交了offset,但是客户端处理过程中出现异常,服务端以为客户端已经消费完毕,解决方式客户端处理完毕后手动提交offset;


6. 如何保证消息的有序性 (生产者为binlog对一条数据进行增删改,如果不保证顺序性)
场景:1)rabbitMQ中一个queue多个consumer
2)kafka:一个topic,一个partition,一个consumer consumer中使用多线程处理
针对ActiveMQ:可以使用独占消费者,并且是循环里面的当前消费者,或者没有独占消费者。则循环里面的当前消费者即被选中能够消费该条消息。
rabbitMQ:拆分成多个queue,一个queue只有一个consumer或者总共一个queue但是对应一个consumer 然后consumer内部使用队列进行存储然后分发进行处理;
kafka:一个topic,一个partition,一个consumer 使用单线程消费 写到N个内存queue中,然后N个线程共同消费同一个queue;(根据业务id进行hash分别交给对应的线程处理)
写入一个partition中的数据一定有顺序的,生产者在写的时候可以指定一个key,这个key相关的数据一定会被写到同一个partition中并且是有顺序的;?????
???? 一个queue 如何配置为多个consumer或者只有一个consumer?


7、如果消息存在积压如何处理?(消息队列的延时以及过期失效问题?消息队列满了如何处理?有几百万消息持续积压几小时)
分析积压原因:
1)如果消费者挂了,消费者重启,增加消费者 但是需要监控数据存储的瓶颈比如数据库;
2)如果消费者正常,消费不过来,新建一个topic 设置10个partition 将接收到的topic发送到新的topic,然后让原有消费者改下topic连接新的patition进行消费;

消息队列的失效问题(过期时间引起):禁止消息队里过期,如果数据丢失了,需要手动写程序将丢失的数据通过程序补回来进行查找;

8、如何设计一个消息队列系统
1) 支持可伸缩 快速扩容,增加吞吐量和容量, 可以参考kafka理念:broker->topic-->partition 每一个partition分一台机器,存放一部分数据;如果现有资源不够了 给topitc增加partition,然后进行数据迁移,增加机器;
2) 数据持久化 持久化采用顺序写,就没有磁盘随机读写的寻址开销了,磁盘顺序读写的性能很高,借鉴kafka的思路;
3) 可用性 采用kafka的高可用保障机制 多副本机制,leader机制
4) 数据0丢失 可以采用kafka数据0丢失方案;


9. ⽤过哪些 MQ,和其他 mq 比较有什什么优缺点, MQ 的连接是线程安全的吗,你们公司的MQ 服务架构怎样的


7. kafka 吞吐量高的原因。

8. kafka 和其他消息队列的区别, kafka 主从同步怎么实现

9. 利用 mq 怎么实现最终一致性

10. 使⽤ kafka 有没有遇到什么问题,怎么解决的

11. MQ 有可能发生重复消费,如何避免,如何做到幂等

12. MQ 的消息延迟了怎么处理,消息可以设置过期时间么,过期了你们⼀般怎么处理


16,kafka,activemq,rabbitmq本质区别是啥


rabbitMQ: https://www.jianshu.com/p/787d155ff4e1

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!