首页 > 其他分享 >为什么使用消息队列

为什么使用消息队列

时间:2024-04-24 23:46:25浏览次数:27  
标签:为什么 队列 partition queue kafka Queue 消息 数据

消息队列的基本作用

  • 解耦
  • 异步
  • 削峰

引入消息队列会导致什么

  • 1.降低系统的可用性:系统引入的外部依赖越多,越容易挂掉
  • 2.系统的复杂度变高:使用 MQ 后可能需要保证消息没有被重复消费、处理消息丢失的情况、保证消息传递的顺序性等等问题
  • 3.一致性问题:A 系统处理完了直接返回成功了,但问题是:要是 B、C、D 三个系统那里,B 和 D 两个系统写库成功了,结果 C 系统写库失败了,就造成数据不一致了。

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

RabbitMQ:镜像集群模式

rabbit是基于主从做高可用的,有三种模式

  • 单机模式:生产环境很少用
  • 普通集群模式:让集群中多节点服务某个queue的读写操作,只是提高了系统的吞吐量
  • 镜像集群模式
    创建的Queue,无论元数据还是queue里的消息都会存在多个实例中,每次写消息到Queue时,都会自动和多个实例的Queue进行消息同步,这样设计的好处:
    任何一个机器宕机不影响其他机器的使用。坏处在于:1. 性能开销太大:消息同步所有机器,导致网络带宽压力和消耗很重;2. 扩展性差:如果某个 Queue 负载很重,即便加机器,新增的机器也包含了这个 Queue 的所有数据,并没有办法线性扩展你的 Queue。

kafka:partition和 replica(副本)机制

Kafka 基本架构是多个 broker 组成,每个 broker 是一个节点。创建一个 topic 可以划分为多个 partition,每个 partition 可以存在于不同的 broker 上,每个 partition 就放一部分数据,这就是天然的分布式消息队列。就是说一个 topic 的数据,是分散放在多个机器上的,每个机器就放一部分数据。

Kafka 0.8 以前,是没有 HA 机制的,任何一个 broker 宕机了,它的 partition 就没法写也没法读了,没有什么高可用性可言。

Kafka 0.8 以后,提供了 HA 机制,就是 replica 副本机制。每个 partition 的数据都会同步到其他机器上,形成自己的多个 replica 副本。然后所有 replica 会选举一个 leader 出来,生产和消费都跟这个 leader 打交道,然后其他 replica 就是 follower。写的时候,leader 会负责把数据同步到所有 follower 上去,读的时候就直接读 leader 上数据即可。Kafka 会均匀的将一个 partition 的所有 replica 分布在不同的机器上,这样才可以提高容错性。

如何保证消息不被重复消费/幂等性

  • 写数据时,先根据主键查询数据是否存在,如果已经存在,则更新数据
  • 数据库的唯一键约束
  • 写redis,分布式锁

如何保证消息不丢失

rabbitMQ:

  • 生产者
    • 1.开启rabbitmq事务(不推荐)太耗性能
    • 2.confirm模式:异步回调 ack消息
  • mq本身丢失:开启rabbitmq持久化(开启2个才行)
    • 1.创建queue时将其设置为持久化,只会持久化queue的元数据
    • 2.将消息的deliverymode设置为2:持久化到磁盘
  • 消费端丢失:关闭rabbitmq的自动ack机制

kafka

  • 生产者:设置acks =all,一定不会丢,无限重试
  • kafka本身丢失
    • 1.给topic设置replication.factor参数,大于1,保证每个partition必须有2个副本
    • 2.在kafka服务端设置 min.insync.replicas,必须大于1,保证leader至少有一个followe保持联系
    • 3.生产端设置acks=all,保证数据必须写入所有replica,才算成功
    • 4.生产端设置retries=max,设置无限重试
  • 消费者丢失:关闭自动提交offset

如何保证消息的顺序性

RabbitMQ:

拆分多个 Queue,每个 Queue一个 Consumer,就是多一些 Queue 而已,确实是麻烦点;或者就一个 Queue 但是对应一个 Consumer,然后这个 Consumer 内部用内存队列做排队,然后分发给底层不同的 Worker 来处理。

Kafka:

  1. 一个 Topic,一个 Partition,一个 Consumer,内部单线程消费,单线程吞吐量太低,一般不会用这个。

  2. 写 N 个内存 Queue,具有相同 key 的数据都到同一个内存 Queue;然后对于 N 个线程,每个线程分别消费一个内存 Queue 即可,这样就能保证顺序性。

大量消息在mq里长时间积压,如何解决

一般这个时候,只能临时紧急扩容了,具体操作步骤和思路如下:

    1. 先修复 consumer 的问题,确保其恢复消费速度,然后将现有 consumer 都停掉;
    1. 新建一个 topic,partition 是原来的 10 倍,临时建立好原先 10 倍的 queue 数量;
    1. 然后写一个临时的分发数据的 consumer 程序,这个程序部署上去消费积压的数据,消费之后不做耗时的处理,直接均匀轮询写入临时建立好的 10 倍数量的 queue;
    1. 接着临时征用 10 倍的机器来部署 consumer,每一批 consumer 消费一个临时 queue 的数据。这种做法相当于是临时将 queue 资源和 consumer 资源扩大 10 倍,以正常的 10 倍速度来消费数据;
    1. 等快速消费完积压数据之后,得恢复原先部署的架构,重新用原先的 consumer 机器来消费消息。

MQ中的消息过期失效怎么办

假设你用的是 RabbitMQ,RabbtiMQ 是可以设置过期时间的,也就是 TTL。如果消息在 Queue 中积压超过一定的时间就会被 RabbitMQ 给清理掉,这个数据就没了。这时的问题就不是数据会大量积压在 MQ 里,而是大量的数据会直接搞丢。这个情况下,就不是说要增加 Consumer 消费积压的消息,因为实际上没啥积压,而是丢了大量的消息。

我们可以采取一个方案,就是批量重导。就是大量积压的时候,直接丢弃数据了,然后等过了高峰期以后开始写程序,将丢失的那批数据一点一点的查出来,然后重新灌入 MQ 里面去,把丢的数据给补回来。

RabbitMQ的重要组件

    1. ConnectionFactory(连接管理器):应用程序与 rabbit 之间建立连接的管理器,程序代码中使用;
    1. Channel(信道):消息推送使用的通道;
    1. Exchange(交换器):用于接受、分配消息;
    1. Queue(队列):用于存储生产者的消息;
    1. RoutingKey(路由键):用于把生成者的数据分配到交换器上;
    1. BindingKey(绑定键):用于把交换器的消息绑定到队列上。

RabbitMQ有几种广播类型

    1. fanout:所有 bind 到此 exchange 的 queue 都可以接收消息;很像子网广播,每台子网内的主机都获得了一份复制的消息。fanout 交换机转发消息是最快的。
    1. direct:通过 routingKey 和 exchange 中的 bindingKey 决定的那个唯一的 queue 可以接收消息;
    1. topic:所有符合 routingKey 所 bind 的 queue 可以接收消息。

kafka

kafka不能脱离zookeeper单独使用,因为kafka使用zookeeper管理和协调kafka的节点服务器

kafka有两种数据保存策略:

  • 按照过期时间保留
  • 按照存储的消息大小保留

kafka的分区策略
所谓分区策略就是决定生产者将消息发送到那个分区的算法

  • 轮询策略:(默认)能保证消息最大限度的平均分配到所有分区上
  • 随机策略:实现随机策略版的partition方法
  • 按消息键保序策略:(key-ordering)可以保证同一个key的所有消息都进入到相同的分区,由于分区下的消息处理是有顺序的,所以称为消息键保序策略
  • 自定义分区策略

标签:为什么,队列,partition,queue,kafka,Queue,消息,数据
From: https://www.cnblogs.com/Skyvswfq/p/18156620

相关文章

  • 为什么使用分布式锁
    为什么使用分布式锁为了保证一个方法或属性在高并发情况下的同一时间只能被同一个线程执行分布式锁应该具备哪些条件?1.在分布式系统环境下,一个方法在同一时间只能被一个机器的一个线程执行2.高可用的获取锁和释放锁3.高性能的获取锁和释放锁4.具备可重入特性5.具备锁实效......
  • Ollama是什么,为什么这么好用
     Ollama是一个开源框架,专为在本地机器上便捷部署和运行大型语言模型(LLM)而设计。以下是其主要特点和功能概述:1.简化部署:Ollama目标在于简化在Docker容器中部署大型语言模型的过程,使得非专业用户也能方便地管理和运行这些复杂的模型。2.轻量级与可扩展:作为轻量级框架,Olla......
  • JZ9 用两个栈实现队列
    classSolution{public://用两个栈实现队列栈是先进后出,队列是先进先出//在队列尾部插入整数voidpush(intnode){//入队就正常入栈stack1.push(node);}//在队列头部删除整数,先进先出intpop(){//将第一个栈中......
  • 风险控制 1、如果你的项目发布后失败,主要的原因会是什么? 2、每个团队列出自己项目中
    项目发布失败的主要原因会是:-需求管理不当:项目未能准确捕捉或满足用户需求。资源分配不当:团队可能缺乏必要的技能或资源来完成项目。时间管理问题:项目可能未能在预定时间内完成。沟通不畅:团队成员之间、团队与利益相关者之间的沟通可能存在问题。技术问题:项目可能遇到无法......
  • 团队练习2:风险控制 1、如果你的项目发布后失败,主要的原因会是什么? 2、每个团队列出自
    学生信息管理系统项目发布后失败的主要原因可能包括:需求分析不准确或不完整,导致系统功能与用户需求不符。技术实现存在问题,如性能低下、安全性不足等。项目管理不善,如进度延误、资源分配不合理等。用户界面设计不佳,导致用户体验差。市场推广不足,用户接受度低。项目中目前面......
  • 项目管理中,为什么关键路径是完成项目的最短时间?
    关键路径方法(CriticalPathMethod)应用于项目管理中,使用该方法可以计算出完成项目所需的最短时间,在理想情况下,至少需要这么长的时间才能完成该项目。关键路径由一系列关键节点组成,这些节点的有序排列构成了关键路径。每个关键节点都是该项目中的其中一个任务,而每个任务包括任务......
  • 项目管理中,为什么关键路径是完成项目的最短时间?
    关键路径方法(CriticalPathMethod)应用于项目管理中,使用该方法可以计算出完成项目所需的最短时间,在理想情况下,至少需要这么长的时间才能完成该项目。关键路径由一系列关键节点组成,这些节点的有序排列构成了关键路径。每个关键节点都是该项目中的其中一个任务,而每个任务包括任务......
  • 团队练习2:风险控制1、如果你的项目发布后失败,主要的原因会是什么?2、每个团队列出自己
    团队练习2:风险控制1、如果你的项目发布后失败,主要的原因会是什么?2、每个团队列出自己项目中目前面临的风险,按严重性排序(例如:团队中有人原来许诺要努力工作,但是后来做了南郭先生,这是一个风险)同时列出每条风险的应对方法;3、针对问题1,你们小组如果出现风险,导致项目发布失败,给出应......
  • 为什么需要分布式存储
    为什么需要分布式存储?这是个好问题,如下是我本人的部分理解。分布式存储,相对应的是集中式存储。作为存储系统,对客户应用而言,可以提供:结构化业务,即块服务。非结构业务,即如下:文件,比如NFS、CIFS/SMB等。对象,比如兼容AWSS3、MSAzureBlob存储等。大数据,比如兼容HDFS。FTP/F......
  • 为什么选择入行分布式存储
    一切都是机缘巧合。转岗前参与的项目出于各种原因无法继续,在原部门已无立足之处,于是阴差阳错之下,转岗加入了分布式存储的开发团队。按照领导的安排,在原服务SE的指导下,一起分担对象服务的方案设计和业务支撑工作。现产品的对象服务,对客户宣称兼容AWSS3,从产品资料看,已具备基本能力......