关于消息队列MQ的常见的问题以及处理

①消息队列的优缺点

优点:异步解耦和削峰

缺点:系统引入mq之后可能存在的一些问题

1系统可用性降低(mq出问题 整个系统就挂了 多了一道环节)

2 系统变复杂 考虑的问题变多(如果系统和mq协调出现问题 往里面加了两条一样的数据 或 是消息积压 或是丢消息 )

3 一致性的问题:a系统给bcd都执行成功才返回结果 结果abc都成功了 d出问题了 导致整个请求给用户返回成功 但是还有部分逻辑没处理成功

②activemq rabbitmq,rocketmq kafka,各种优缺点

万级 万级 10万 10万 (单机吞吐量)

ms 微s ms ms(延时 生产 和消费时间)

会丢 0丢失 0丢失(消息丢失情况)

activemq 底层是java写的,比较成熟但是不适合吞吐量大的场景 且社区更新慢

rabbitmq 性能好,mq功能比较完善,管理界面好用 但是是erlang 语言写的 天生的并发能力好 性能强 延时低(适合中小公司)社区活跃

rocketmq topic达到几百个 消息0丢失,分布式架构 扩展起来方便 阿里开源的 java开发的(团队项目解散 这个项目就黄了,更新维护就没了)

kafka 单机吞吐10万甚至百万 但是 topic 多的话吞吐量下降 功能简单 大数据计算 上 数据采集 日志 吞吐量高 拓展性高

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

rabiitmq的高可用:

普通集群模式分析:从一台去消费数据如果不在 就去其他节点上找数据

缺点1:可能会在rabbitmq会出现大量的数据传输

缺点2 : 可用性几乎不存在任何保证 如果节点挂掉 找不到数据了

镜像集群模式:(在管控台上可以设置这个模式 设置节点上数据是不是要同步到其他队列上)

每一个节点都会将数据进行同步到其他节点上去:(每一个节点都有这个队列的完整镜像,全部数据) 消费的时候 任何一个节点消费都行

kafka的高可用怎么设计:

每台机器上启动一个进程broker进程(集群中的节点)

创建一个topic,指定其partition的数量多个,表明数据存在多台服务器的多个patition上.0.8版本前没有高可用机制的.

如果一台服务器宕机,数据就会丢失,0.8以后,每个patition都有一个副本,通过replica副本机制来实现的

选举为leader其他的副本就是follower 生产者只能往leder里面写数据 消费者也只能从leader里面消费数据

如果leder死掉了 follower中选出一个leader

④为什么会消费到重复的消费?保证消息的幂等性.

kafka 每条消息中都存在一个offset 代表这个消息顺序的序号)

消费者消费之后回去提交offeset 表示已经消费该数据 zookeeperr记录消费者当前消费到了offset那几条数据

如果消费者重启 只需要将没有消费的数据发送过来.

消费者并不是消费完一条数据就立马提交offset 而是定期提交一次offset,在提交之前消费者重启 系统就不知道你消费了没有

幂等性的保障机制

如果重复数据,每次消费一次 数据库中存一次 然后redis中存一下存在这个消息记录 那就不要再插入了

⑤怎么保证消息的可靠性?(怎么保证消息不丢失)一般是confirm机制 异步的,不会阻塞 吞吐量会大一些

生产者 ----> rabbiitmq------->消费者

1 写消息网络传输中消息丢失,mq中没保存下来

2 在mq中暂存于内存中,还没消费 mq挂了 消息丢失

3 消费者消费消息 还没处理就自己挂掉了,但是rabbitmq以为消费者已经处理完了

rabbitmq中的事务 (同步的生产者发送消息的吞吐量下降) 通过try catch 发送消息,出现异常,catch到之后回滚,重试发送消息成功就提交

① 将channal设置成confirm的模式 ②发送消息 ③然后就不用管了 ④ 如果rabbitmq接收到这条消息,会回调本地的接口 说这条消息已经接收到了 ⑤如果报错 回调接口接受失败 可以再次重发

持久化到磁盘中,创建queue时候就持久化

原因:自动ack但是没处理完就ack 此时宕机 数据丢失

处理办法 :消费者autoack机制 关闭 在处理完消息之后,手动的ack 如果在消息没处理完 rabbitmq会将消息给其他的消费者来处理.

kafka数据丢失:

唯一数据丢失的情况就是 消费到这个消息 自动提交offset 让kafka确保消费导数据再提交offset

数据在存到leader时候 还没来的及将数据发送到follower上.此时leader宕机 数据会丢失

每个patition至少两个副本,至少保证有一个follower和leader有联系 生产者必须acks=all 消息写入所有的副本中 才认为消息写入成功 如果失败的话 无限重试 .

⑥消息队列中保证消息的顺序进行

比如在主从同步 biglog mysql-->mysql 这个肯定要按顺序来进行操作

rabbitmq中:

保证数据消费的数据放在一个队列中 只让一个消费者消费 就能保证其数据结构的顺序进行

kafka中:

一个消费者就消费一个patition 如果消费者中间存在多个线程去进行处理的话 消息会错乱的

(4核8g 开 32个线程 每秒1000多个)

内存队列 中也是有顺序的 + 多线程 来处理 每个线程处理也是有顺序的

⑦不是分布式的mq 如果数据量很大 数据产生积压 无法容纳所有数据怎么办呢?

实际开发中就是让消费者故障,只能让消费者重新消费 紧急扩容.将3个patition中取出的数据 在放到30个patition 中去进行 操作 时间就可以缩短为原来十倍

mq延时过期怎么处理 ,设置过期之后消息会自动删除 生产中一般都不会用的

只能手动去查出来 然后重新导入mq中

如果是磁盘满了 怎么办 呢 只能写个临时程序 让消费者快速消费

⑧如果自己设计一个消息中间件(mq的架构)

mq支持扩容 分布式 参考kafka架构 每个机器房部分数据 顺序写 持久化到磁盘 多副本的保障机制

猜你喜欢

转载自blog.csdn.net/qq_27229113/article/details/109398057