MQ(消息队列)简述

MQ(消息队列)简述

如今市面上常见的MQ有:

RabbitMQ

ActiveMQ

RocketMQ

Kafka

在使用这些MQ之前,首先思考几个问题

1.为什么要使用MQ?

2.不同的MQ有什么优缺点?

针对为什么使用MQ,主要有三个应用场景:削峰解耦异步

但是!MQ除了有可观的优点以外,还是有不可忽视的缺点的,一个系统如果引入了MQ,那么会存在以下问题:

1.系统的复杂度提高(需要考虑数据的一致性、准确性、不重复消费、不丢失数据等)

2.系统的可用性降低(硬生生拉个MQ过来,需要考虑MQ挂了应该怎么办,系统崩溃可不好受)

针对这些方面,列出如下表1-1

特性 ActiveMQ RabbitMQ RocketMQ Kafka
单机吞吐量 万级,比Kafka、RocketMQ低一个级别 同ActiveMQ 10万级,高吞吐 同RocketMQ,主要用在数据采集,实时数据计算
topic数量对吞吐量的影响 - - 支持几百到几千的topic数量,吞吐量会有小幅度的下降 几十到几百,尽量topic数量不要太多,是在需要支撑大规模的场景,可以增加节点
时效性 ms级 微s级,延迟最低 ms级别 ms级别
可用性 高,基于从架构实现高可用 同ActiveMQ 非常高,分布式架构 非常高,分布式,数据高可靠,少数节点宕机不会导致数据丢失
消息可靠性 有较低的概率丢失数据 基本不丢失 通过参数调优,可以做到0丢失 通过参数调优,可以做到0丢失
功能支持 MQ领域功能极其完备 基于Erlang开发,性能好,培训成本高 MQ功能比较完善,分布式、扩展性好 功能比较简单,主要用于实时计算、数据采集领域

互联网早期都是用ActiveMQ,可以由于不支持大规模数据吞吐场景,而且社区也不活跃,所以现在使用的很少,后来开始使用RabbitMQ,但是由于Erlang语言给Java工程师去了解其底层造成了困扰,培训成本太高,如今越来越多的公司开始使用RocketMQ,毕竟是alibaba出品,而且交给apache社区进行管理与维护,kafka在大数据领域也是使用非常广泛,用于数据采集、实时计算领域,常与Flink、SparkStreaming配合使用。

中小公司用RabbitMQ、大公司用RocketMQ和Kafka

如何保证MQ 的高可用

RabbitMQ的高可用

rabbitMQ的高可用是基于master - slaves的架构,虽然rabbitMQ属于非分布式高可用,但是很多分布式集群的高可用都使用的类似架构,那么rabbitMQ的高可用是怎么实现的呢?

RabbitMQ有三种模式:

单机模式、普通集群模式、镜像集群模式

单机模式

一般就是Demo级别的,一般就是本地启动玩玩,真正生产没人使用

普通集群模式(无高可用性)

普通集群模式,意思就是在多台机器上启动多个 RabbitMQ 实例,每个机器启动一个。你创建的 queue,只会放在一个 RabbitMQ 实例上,但是每个实例都同步 queue 的元数据(元数据可以认为是 queue 的一些配置信息,通过元数据,可以找到 queue 所在实例),你消费的时候,实际上如果连接到了另外一个实例,那么那个实例会从 queue 所在实例上拉取数据过来。

镜像集群模式

有高可用,每个节点都保存数据及原数据的全量、一个节点挂掉并不会影响数据的完整性,但是对带宽磁盘消耗非常大,也没有扩展性可言,以为就算添加一个节点,也只会保存全量的数据。

Kafka的高可用

kafka在0.8版本以后引入了HA机制,这里涉及到以下概念

  • broker 一个broker就是kafka集群的节点
  • topic 消息的主题
  • Partition 每个topic都可以按照分区器分为多个分区
  • replication 每个partition都可以有多个副本
  • leader 真正负责读写的消息副本
  • follower 只负责从leader拉去数据
  • ISR 副本同步机制,kakfa源码中通过一个ISR来维护leader与候选的follower
  • HW 高水位,leader与follower的共同最高水位
  • LEO 单个replication的最高offset+1

leader负责读写,leader挂掉了,通过ISR机制从follower中重新选举leader

如何保证消息不重复消费(幂等性)

从zookeeper节点中查看TopicAndPartitionoffset

[zk: localhost:2181(CONNECTED) 5] ls /brokers/topics/__consumer_offsets/partitions
[44, 45, 46, 47, 48, 49, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43]
#自动提交offset就是将数据提交到zk中
Kafka什么情况下会产生数据重复消费?

在kafka中有offset的概念,代表消息的偏移量,consumer默认每隔一段时间都会将offset提交到kafka的,如果消费者在消费完一段数据但是offset没有来得及提交消费者线程挂掉之后,下次消费,之前消费过的数据就会重复消费一次。

一条数据重复出现两次,数据库里就只有一条数据,这就保证了系统的幂等性

幂等性,通俗点说,就一个数据,或者一个请求,给你重复来多次,你得确保对应的数据是不会改变的,不能出错

幂等性具体示例:

  • 比如你拿个数据要写库,你先根据主键查一下,如果这数据都有了,你就别插入了,update 一下好吧。

  • 比如你是写 Redis,那没问题了,反正每次都是 set,天然幂等性。

  • 比如你不是上面两个场景,那做的稍微复杂一点,你需要让生产者发送每条数据的时候,里面加一个全局唯一的 id,类似订单 id 之类的东西,然后你这里消费到了之后,先根据这个 id 去比如 Redis 里查一下,之前消费过吗?

    如果没有消费过,你就处理,然后这个 id 写 Redis。

    如果消费过了,那你就别处理了,保证别重复处理相同的消息即可。

  • 比如基于数据库的唯一键来保证重复数据不会重复插入多条。

    因为有唯一键约束了,重复数据插入只会报错,不会导致数据库中出现脏数据。

Kafka什么情况下会丢失数据

要弄清楚这个问题,我们得先明白几个概念:

producer、kafka-cluster 、consumer

producer --[ack]–> kafka-cluster属于一种rpc远程处理连接机制

1.在ProducerConfig中可以设置ack = 0 、-1(all) 、1

2.通过replication.factor设置每隔分区的副本数量至少为2

3.min.insync.replicas大于1,要求leader感应到至少1个follower没掉队

4.retries=MAX消息写入失败的重试次数

kafka-direct消费参考链接

https://github.com/shufang000/SparkStreaming-DirectKafka010/blob/master/pom.xml

发布了65 篇原创文章 · 获赞 3 · 访问量 2163

猜你喜欢

转载自blog.csdn.net/shufangreal/article/details/104628146