消息队列为什么要用消息队列,都有什么优缺点?
解耦 需要去考虑你负责的系统中是否有类似的场景,一个系统调用了多个系统和模块,互相之间的调用很复杂,维护起来很麻烦。但是这个调用并不需要直接同步调用接口,如果用MQ给它异步化解耦,也是可以的,你就需要 考虑在你的项目中,是不是可以运用这个MQ去进行解耦。在简历中体现出来 异步化异步化可以大幅度提升高延迟接口的性能 削锋:未使用MQ的时候:
使用MQ以后:
系统架构中引入MQ后可能存在的缺陷:
问题2:kafka,activeMq,rabbitMq,rocketMq 都有什么优缺点?
如何保证消息队列的高可用?问的是你用的哪种MQ,是如何保证高可用的?
3.镜像集群模式 这个才是rabbit高可用的解决方案,创建的queue,无论元数据还是queue里的消息都会存在与多个实例中,然后每次写消息到queue中时,都会自动把消息放到多个实例的queue中进行数据同步。
如何开启镜像策略: 在rabbitMq有一个管理控制台,在后台新增一个策略,这个策略就是镜像集群模式的策略,指定的时候可以要求数据同步到所有节点,也可以要求同步到指定数量的节点,然后再次创建queue时,应用这个策略,就会自动同步数据到其他节点上 4.kafka的高可用性: 一个最基本的架构认识,多个broker组成,每个broker是一个节点,创建一个topic,这个topic可以划分为多个partition,每个partition可以存在与不同的broker上,每个partiton就放一部分数据。 kafka是一个天然的分布式的消息队列,就是说一个topic的数据分布在多个机器上面,每个机器就放一部分数据
如何保证消息不被重复消费?如何保证消费的时候是幂等?
幂等性: 一条数据或者一个请求,给你重复来多次,你得确保对应的数据是不会改变的,不能出错
如何保证幂等呢? 一条数据重复出现了两次,数据库里只有一条数据,这就保证了系统的幂等性 (1) 比如拿到数据要入库,你先根据主键查一下,如果这个数据有了,就别再插入了,update一下就好 (2) 比如是写redis,那就没问题,因为是set,天然幂等的。 (3) 如果不是以上所述的场景,你需要让生产者发送数据的时候,添加一个全局唯一的ID,然后到了消费者的时候,现根据id去排查,之前是否消费过? 如果没有就处理,然后这个ID 写入到map或者redis中;如果消费过了,那就别处理了,保障消息不被重复处理即可;
如何保证消息的可靠性传输?要是消息丢了怎么办?1).生产者弄丢数据 生产者将数据发送到rabbitmq的时候,可能数据就在半路给弄丢了,因为网络原因,都用可能 此时可以选择用rabbitmq提供的事务功能,就是生产者发送数据之前开启rabbitMQ事务(channel.txSelect) ,然后发送消息,如果消息没有成功被rabbitmq接收到,那么生产者会收到异常报错,此时就可以回滚事务(channel.txRollback),然后尝试重发消息;如果收到消息,那么可以提交事务(channel.txCommit).但是问题是,rabbitMQ事务机制一搞,吞吐量就会下来,因为太耗性能。
2).MQ自己弄丢了数据对于rabbitMQ,可以开启持久化,写入的消息以后会持久化到磁盘里,哪怕是mq自己挂了,恢复之后会自动读取之前存储的数据; 设置持久化有两个步骤:
总结: 生产者处的方案:开启confirm模式,通过回调接口来得知是否成功发送到MQ MQ内部的方案: 通过持久化到磁盘的方式,避免机器宕机导致内存中的数据丢失 消费者处的方案: 关闭 autoAck ,当消费者消费并处理完后手动进行ACK 3).Kafka
一般要求有如下设置步骤:
如何保证消息的顺序性?先看看顺序出错的场景
rabbitMQ如何保证消息的顺序性:如果有多个消费者,就配置多个queue,将需要保证顺序的消息全部写到一个queue里,这样就能保证消息的顺序性
kafka顺序性问题
1个topic,3个partition,3个consumer,每个消费者消费一个partition,需要保证顺序的消息都放入同一个partiton,但是如果一个消费者开启多个线程来处理,还是无法保证消息的顺序性。 kafka如何保证消息的顺序性:
解决办法:每个消费者内部设置多个内存队列,对消息的key做hash,将需要保证顺序的消息映射到同一个内存队列中,每个线程负责处理一个内存队列
如何解决消息队列的延时过期失效问题?消息队列满了以后该如何处理?有几百万消息持续积压几个小时,说说怎么解决? 本质针对的场景是,消费端出问题了,不消费了,或者消费端消费速度很慢,可能消息队列集群的磁盘都快满了,都没消费者来消费,导致整个就积压了几个小时,这个时候该怎么办?
RabbitMQ中由于消息积压导致过期被清理了怎么办 假设你用的是rabbitmq,rabbitmq是可以设置过期时间的,就是TTL,如果消息在queue中积压超过一定的时间就会被rabbitmq给清理掉,这个数据就没了。 这就不是说数据会大量积压在mq里,而是大量的数据会直接搞丢。 这个情况下,就不是说要增加consumer消费积压的消息,因为实际上没啥积压,而是丢了大量的消息。 我们可以采取一个方案,就是批量重导。就是大量积压的时候,我们当时就直接丢弃数据了,然后等过了高峰期以后,这个时候我们就开始写程序,将丢失的那批数据,写个临时程序,一点一点的查出来,然后重新灌入mq里面去,把白天丢的数据给他补回来。 假设1万个订单积压在mq里面,没有处理,其中1000个订单都丢了,你只能手动写程序把那1000个订单给查出来,手动发到mq里去再补一次
如果让你来写一个消息队列,该如何进行架构设计?说一下你的思路?
|
|