当然在选择之前一般也会做一些调研,不一样的选择意味着未来踩不一样的坑
公司也会选择直接购买MQ的云服务,这不失为省钱的一个好办法
RabbitMQ是采用Erlang语言实现的AMQP协议的消息中间件,最初起源于金融系统,用于在分布式系统中存储转发消息
Kafka起初是由LinkedIn公司采用Scala语言开发的一个分布式、多分区、多副本且基于zookeeper协调的分布式消息系统,它是一种高吞吐量的分布式发布订阅消息系统,以可水平扩展和高吞吐率而被广泛使用。
选型参考维度:
1.功能
子维度:
a.优先级队列:只要生产者生产速度远大于消费者消费速度,造成消息堆积的时候,才会考虑这个这些堆积消息的顺序问题
b.延迟队列--“三十分钟之内未付款,订单自动取消”?这个是延迟队列的一种典型应用场景
b1.基于消息的延迟:为每条消息设置不同的延迟时间(影响性能)
b2.基于队列的延迟:比如5s、10s、30s、1min、5mins、10mins等,每个队列中消息的延迟时间都是相同的,
为异常的处理提供的一种机制保障
c.死信队列:由于某些原因消息无法被正确的投递,为了确保消息不会被无故的丢弃,一般将其置于一个特殊角色的队列
回退队列:试想如果消费者在消费时发生了异常,那么就不会对这一次消费进行确认(Ack),进而发生回滚消息的操作之后消息始终会放在队列的顶部,然后不断被处理和回滚,导致队列陷入死循环
每个队列设置一个回退队列----实际情况下,回退队列的角色可以由死信队列和重试队列来扮演。
d.重试队列:是一种回退队列。消费端消费消息失败时,为防止消息无故丢失而重新将消息回滚到Broker中。与回退队列不同的是重试队列一般分成多个重试等级,每个重试等级一般也会设置重新投递延时,重试次数越多投递延时就越大。举个例子:消息第一次消费失败入重试队列Q1,Q1的重新投递延迟为5s,在5s过后重新投递该消息;如果消息再次消费失败
举个例子:消息第一次消费失败入重试队列Q1,Q1的重新投递延迟为5s,在5s过后重新投递该消息;如果消息再次消费失败则入重试队列Q2,Q2的重新投递延迟为10s,在10s过后再次投递该消息。
以此类推,重试越多次重新投递的时间就越久,为此需要设置一个上限,超过投递次数就入死信队列
重试队列d与延迟队列b有相同的地方,都是需要设置延迟级别
延迟队列动作由内部触发,重试队列动作由外部消费端触发
延迟队列作用一次,而重试队列的作用范围会向后传递
e.消费模式:
消费模式分为推(push)模式和拉(pull)模式。
推模式:是指由Broker主动推送消息至消费端 实时性较好,不过需要一定的流制机制来确保服务端推送过来的消息不会压垮消费端
拉模式:指消费端主动向Broker端请求拉取(一般是定时或者定量)消息,实时性较推模式差,但是可以根据自身的处理能力而控制拉取的消息量。
f:消息回溯:---指消息在消费完成之后,还能消费到之前被消费掉的消息
对消息而言,经常面临的问题是“消息丢失”,至于是真正由于消息中间件的缺陷丢失还是由于使用方的误用而丢失一般很难追查,
如果消息中间件本身具备消息回溯功能的话,可以通过回溯消费复现“丢失的”消息进而查出问题的源头之所在
g:消息堆积+持久化
流量削峰是得益于其消息堆积能力
消息堆积分
1.内存式堆积(RabbitMQ)
2.磁盘式堆积 (kafka)--所有的消息都存储在磁盘
RabbitMQ是典型的内存式堆积,不过也并非绝对,在某些条件触发后会有
换页动作来将内存中的消息换页到磁盘(换页动作会影响吞吐),
或者直接使用惰性队列来将消息直接持久化至磁盘中
h:消息幂等性
2.性能
有时候性能比功能还要重要,况且性能和功能很多时候是相悖的,鱼和熊掌不可兼得,Kafka在开启幂等、事务功能的时候会使其性能降低,RabbitMQ在开启rabbitmq_tracing插件的时候也会极大的影响其性能
消息中间件的性能一般是指其吞吐量,虽然从功能维度上来说,RabbitMQ的优势要大于Kafka,但是Kafka的吞吐量要比RabbitMQ高出1至2个数量级,一般RabbitMQ的单机QPS在万级别之内,而Kafka的单机QPS可以维持在十万级别,甚至可以达到百万级。
消息中间件的吞吐量始终会受到硬件层面的限制。就以网卡带宽为例,如果单机单网卡的带宽为1Gbps,如果要达到百万级的吞吐,那么消息体大小不得超过(1Gb/8)/100W,即约等于134B,换句话说如果消息体大小超过134B,那么就不可能达到百万级别的吞吐。这种计算方式同样可以适用于内存和磁盘
3. 可靠性+可用性
消息丢失是使用消息中间件时所不得不面对的一个同点,其背后消息可靠性也是衡量消息中间件好坏的一个关键因素
其是在金融支付领域,消息可靠性尤为重要。然而说到可靠性必然要说到可用性,注意这两者之间的区别,消息中间件的可靠性是指对消息不丢失的保障程度;而消息中间件的可用性是指无故障运行的时间百分比,通常用几个9来衡量。
从狭义的角度来说,分布式系统架构是一致性协议理论的应用实现
Kafka:其采用的是类似PacificA的一致性协议,通过ISR(In-Sync-Replica)来保证多副本之间的同步,并且支持强一致性语义(通过acks实现)
RabbitMQ:镜像环形队列实现多副本及强一致性语义的。多副本可以保证在master节点宕机异常之后可以提升slave作为新的master而继续提供服务来保障可用性