一、为什么使用消息队列?
消息队列特别适用于高并发环境:
1、解耦:A系统提供了一个用户服务,BCD三个系统分别依赖于A系统的服务
图①未解耦
图②通过消息队列解耦
2、异步:因为同步会带来时间的等待,而互联网企业要求对于用户的直接操作,一般每个请求都必须要在200ms以内完成,这样对于用户来说是无感知的
图①同步
图②异步请求(可以多个MQ来对应系统,也可以使用同一台MQ集群或者MQ服务器用不同的主题来进行标记)
3、削峰:假若每天0:00到12:00,每秒并发请求数50个,12:00-13:00,每秒请求暴增5K+,如果系统直接对接关系型数据库(MySQL),每秒就会发送5K+条sql到数据库上,一般MySQL只能扛每秒2K的请求
图①直接访问数据库
图②通过消息队列访问数据库
消息队列缺点:
1、系统的可用性降低了(万一MQ挂了怎么处理?)
2、系统的复杂性提高了
①有没有重复消费
②数据有没有丢失
③消息的顺序如何处理
3、一致性问题
请求在消息队列中并没有在数据库,它提示你消费成功了,那你如何知道是否成功了?若到A系统是成功了,到B系统和C系统失败了,这就导致数据出现不一致的情况。
二、ActiveMQ、RabbitMQ、Kafka的对比
1、ActiveMQ:
1.1)Java写的消息队列
1.2)提供了丰富的客户端
1.3)配置上实用的是对Java和Spring比较友好的XML
1.4)可以作为一个jar包放到项目里,使用代码进行启动和配置
1.5)支持复制集群
1.6)工作模型:
1.6.1)queue(队列):生产者往queue发消息,消费者从queue里取消息
1.6.2)topics(主题):生产者往broker发消息,每个消息包含一个topic。消费者订阅自己感兴趣的topic
1.7)支持mqtt、ssl
1.8)单机吞吐量:万级
1.9)时效:ms级
1.10)消息可靠性:丢失消息的概率比较低
2、RabbitMQ:
2.1)erlang写的,安装完不到10M
2.2)配套设施强大:实例,用户规划权限,监控系统
2.3)也有queue(队列)和topic(主题)的概念,又引入了exchange的概念
2.3.1)要指定消息的key,作为路由键用
2.3.2)指定发送到那个exchange(交换器)
2.4)exchange有四种:direct、fanout、topic、header
2.4.1)默认的交换器是direct(key被设定死了)
2.4.2)fanout
2.4.3)topic
2.4.3.1)*表示部分字符
2.4.3.2)#表示剩余字符
2.4.4)header(少见)
2.5)支持主从复制和集群
2.5.1)普通集群
2.5.2)镜像队列,性能比普通集群低
2.6)以插件的形式支持mqtt,以及和spring整合
2.7)单击吞吐量:万级
2.8)时效性:微秒级(延迟最低)
2.9)可用性:高
2.10)消息可靠性:基本不丢
2.11)功能支持:配套设置比较完备
3、Kafka:
3.1)Scala实现,是一门可以运行在JVM虚拟机上的语言
3.2)Kafka中只有topic
3.3)Kafka的topic中有分区partition,并且分区是冗余存储的(专为分布式诞生)
3.4)Kafka中的消息在partition中的存储是采用的偏移量的机制,所以在同一个partition中,消息消费的顺序是可以得到保证的
3.5)Kafka中消息的删除策略有两种,所以Kafka支持重复消费(RabbitMQ、ActiveMQ不支持重复消费,被消费后立马就会被删除)
3.5.1)时间策略,相当于过期时间,过了这个时间就会自动删除
3.5.2)容量:超过了一定的量,会把最早的消息进行删除
3.6)Kafka支持多个应用程序消费同一个主题中的消息(解释一下:Queue是队列,Topic是主题)
3.7)消费者要指出自己属于哪一个ConsumerGroup,每个消费者都可以读取多个分区
但是 一个分区在同一个ConsumerGroup中只会被同一个消费者消费(下图解释)
3.8)Kafka支持MQTT
3.9)创建一个topic是一个很重的操作,Kafka仅仅可以作为MQTT的输入(若让Kafka去给一个一个硬件去发消息,这不是它擅长的,可以考虑RabbitMQ)
3.10)Kafka提供了流式计算,可以做一些数据的初步清理