无常是常

分享技术见解、学习心得和生活感悟

最新文章

消息中间件选型

本文主要对比常用的三种中间件优劣势,包含RocketMQ、Kafka、RabbitMQ。

Kafka

优势

  • Kafka的吞吐量几乎是行业里最优秀的,在常规的机器配置下,一台机器可以达到每秒十几万的QPS,相当的强悍。
  • Kafka性能也很高,基本上发送消息给Kafka都是毫秒级的性能。可用性也很高,Kafka是可以支持集群部署的,其中部分机器宕机是可以继续运行的。
  • Kafka技术在各大公司里的使用,基本行业里的一个标准,是把Kafka用在用户行为日志的采集和传输上,比如大数据团队要收集APP上用户的一些行为日志,这种日志就是用Kafka来收集和传输的。

劣势

  • Kafka比较为人诟病的一点,似乎是丢数据方面的问题,因为Kafka收到消息之后会写入一个磁盘缓冲区里,并没有直接落地到物理磁盘上去,所以要是机器本身故障了,可能会导致磁盘缓冲区里的数据丢失。
  • Kafka另外一个比较大的缺点,就是功能非常的单一,主要是支持发送消息给他,然后从里面消费消息,其他就没有什么额外的高级功能了。所以基于Kafka有限的功能,可能适用的场景并不是很多。

总结

Kafka适用于那种日志适当丢失数据是没有关系的,而且一般量特别大,要求吞吐量要高,一般就是收发消息,不需要太多的高级功能,所以Kafka是非常适合这种场景的。

RabbitMQ

优势

  • RabbitMQ的优势在于可以保证数据不丢失,也能保证高可用性,即集群部署的时候部分机器宕机可以继续运行,然后支持部分高级功能,比如说死信队列,消息重试之类的,这些是他的优点。
  • 在RocketMQ出现之前,国内大部分公司都从ActiveMQ切换到RabbitMQ来使用,包括很多一线互联网大厂,而且直到现在都有很多中小型公司在使用RabbitMQ,所以说RabbitMQ网上的资料相对多,而且社区非常活跃,更新频率非常快。

劣势

  • RabbitMQ的吞吐量是比较低,一般就是每秒几万的级别,所以如果遇到特别特别高并发的情况下,支撑起来是有点困难的。
  • RabbitMQ进行集群扩展的时候(也就是加机器部署),比较麻烦。
  • 另外还有一个较为致命的缺陷,就是他的开发语言是erlang,国内很少有精通erlang语言的工程师,因此也没办法去阅读他的源代码,甚至修改他的源代码。

总结

现在行业里的一个情况是,很多BAT等一线互联网大厂都切换到使用更加优秀的RocketMQ了,但是很多中小型公司觉得RabbitMQ基本可以满足自己的需求还在继续使用中,因为中小型公司并不需要特别高的吞吐量,RabbitMQ已经足以满足他们的需求了,而且也不需要部署特别大规模的集群,也没必要去阅读和修改RabbitMQ的源码。

RocketMQ

优势

  • RocketMQ的吞吐量很高,单机可以达到10万QPS以上,而且可以保证高可用性,性能很高,而且支持通过配置保证数据绝对不丢失,可以部署大规模的集群,还支持各种高级的功能,比如说延迟消息、事务消息、消息回溯、死信队列、消息积压,等等。

  • RocketMQ是基于Java开发的,符合国内大多数公司的技术栈,很容易就可以阅读他的源码,甚至是修改他的源码。

  • RocketMQ是非常适合用在Java业务系统架构中的,因为他很高的性能表现,还有他的高阶功能的支持,可以让我们解决各种业务问题。

劣势

  • RocketMQ也有一点美中不足的地方,就是经过调查发现,RocketMQ的官方文档相对简单一些,但是Kafka和RabbitMQ的官方文档就非常的全面和详细,这可能是RocketMQ目前唯一的缺点。

总结

RocketMQ相对来说比较完美的一个消息中间件,在支撑高吞吐量的同时,而且还支持很多高阶的功能,很适合以Java为技术栈的公司使用。

本文主要对比常用的三种中间件优劣势,包含RocketMQ、Kafka、RabbitMQ。

Kafka

优势

  • Kafka的吞吐量几乎是行业里最优秀的,在常规的机器配置下,一台机器可以达到每秒十几万的QPS,相当的强悍。
  • Kafka性能也很高,基本上发送消息给Kafka都是毫秒级的性能。可用性也很高,Kafka是可以支持集群部署的,其中部分机器宕机是可以继续运行的。
  • Kafka技术在各大公司里的使用,基本行业里的一个标准,是把Kafka用在用户行为日志的采集和传输上,比如大数据团队要收集APP上用户的一些行为日志,这种日志就是用Kafka来收集和传输的。

劣势

  • Kafka比较为人诟病的一点,似乎是丢数据方面的问题,因为Kafka收到消息之后会写入一个磁盘缓冲区里,并没有直接落地到物理磁盘上去,所以要是机器本身故障了,可能会导致磁盘缓冲区里的数据丢失。
  • Kafka另外一个比较大的缺点,就是功能非常的单一,主要是支持发送消息给他,然后从里面消费消息,其他就没有什么额外的高级功能了。所以基于Kafka有限的功能,可能适用的场景并不是很多。

总结

Kafka适用于那种日志适当丢失数据是没有关系的,而且一般量特别大,要求吞吐量要高,一般就是收发消息,不需要太多的高级功能,所以Kafka是非常适合这种场景的。

RabbitMQ

优势

  • RabbitMQ的优势在于可以保证数据不丢失,也能保证高可用性,即集群部署的时候部分机器宕机可以继续运行,然后支持部分高级功能,比如说死信队列,消息重试之类的,这些是他的优点。
  • 在RocketMQ出现之前,国内大部分公司都从ActiveMQ切换到RabbitMQ来使用,包括很多一线互联网大厂,而且直到现在都有很多中小型公司在使用RabbitMQ,所以说RabbitMQ网上的资料相对多,而且社区非常活跃,更新频率非常快。

劣势

  • RabbitMQ的吞吐量是比较低,一般就是每秒几万的级别,所以如果遇到特别特别高并发的情况下,支撑起来是有点困难的。
  • RabbitMQ进行集群扩展的时候(也就是加机器部署),比较麻烦。
  • 另外还有一个较为致命的缺陷,就是他的开发语言是erlang,国内很少有精通erlang语言的工程师,因此也没办法去阅读他的源代码,甚至修改他的源代码。

总结

现在行业里的一个情况是,很多BAT等一线互联网大厂都切换到使用更加优秀的RocketMQ了,但是很多中小型公司觉得RabbitMQ基本可以满足自己的需求还在继续使用中,因为中小型公司并不需要特别高的吞吐量,RabbitMQ已经足以满足他们的需求了,而且也不需要部署特别大规模的集群,也没必要去阅读和修改RabbitMQ的源码。

RocketMQ

优势

  • RocketMQ的吞吐量很高,单机可以达到10万QPS以上,而且可以保证高可用性,性能很高,而且支持通过配置保证数据绝对不丢失,可以部署大规模的集群,还支持各种高级的功能,比如说延迟消息、事务消息、消息回溯、死信队列、消息积压,等等。

  • RocketMQ是基于Java开发的,符合国内大多数公司的技术栈,很容易就可以阅读他的源码,甚至是修改他的源码。

  • RocketMQ是非常适合用在Java业务系统架构中的,因为他很高的性能表现,还有他的高阶功能的支持,可以让我们解决各种业务问题。

劣势

  • RocketMQ也有一点美中不足的地方,就是经过调查发现,RocketMQ的官方文档相对简单一些,但是Kafka和RabbitMQ的官方文档就非常的全面和详细,这可能是RocketMQ目前唯一的缺点。

总结

RocketMQ相对来说比较完美的一个消息中间件,在支撑高吞吐量的同时,而且还支持很多高阶的功能,很适合以Java为技术栈的公司使用。

消息中间件是什么?

1、了解消息中间件之前先了解一下什么是“同步”?

通常业务系统直接的调用如下图所示:

假设系统A收到了一个请求,可能是用户通过浏览器或者APP发起的,这时候系统A收到请求后马上去调用系统B,然后系统B再把返回结果返回给系统A,系统A才能返回给用户。如下图所示:

以上就是所谓的**“同步”**调用。这个同步的意思就是各个系统联动都是同步依次进行的,一个系统先动,然后立马带动另外一个系统一起动,最后大家依次干完活以后再返回结果。

2、如何依托消息中间件实现异步?

我们往系统A和系统B之间加入一个消息中间件,简称为“MQ”,也就是消息队列。

加入消息队列之后如何通信呢?

其实就是系统A执行完逻辑后给MQ中发送一条消息,然后就直接把结果返回给用户了。

(注:前提是系统A返回给用户的结果不依赖于系统B的返回结果。假设系统B为短信系统,系统A向MQ发送一条发送短信的消息指令,系统A并不关心短信是否立即发送,只要最终在有效的时间内发送成功就行了。)

如上图所示,系统B什么时候执行自己的任务呢?

这时候系统B根据自己的情况,可能是系统A投递消息到MQ之后的1秒内,也可能是1分钟之后,多长时间都有可能,不管多长时间,系统B肯定会从MQ里获取到一条属于自己的消息。

3、消息中间件到底有什么用?

假设系统A要调用系统B干一些事,然后系统A先执行一些操作,需要耗费20ms,接着系统B执行一些操作,需要200ms,所以总共需要220ms。如下图所示:

如果在系统A和系统中间加一个MQ呢?

系统A干完自己的事情耗时20ms,然后发一个消息到MQ耗时5ms,然后就直接返回结果给用户,总计耗时25ms。系统B从MQ中获取消息花费200ms和用户就没有关系了。所以用户只需等待25ms就收到结果了。如下图所示:

假设系统A调用系统B出现故障呢?因为系统A调用系统B肯定返回异常,此时系统A是不是也得返回异常给用户?而系统A是不是还要去处理这个异常?

这一切是因为系统A和系统B通过同步调用的模式耦合在一起,所以系统B一旦出现故障,很肯能影响系统A也有故障,而且系统A还得去关心系统B的故障,去处理对应的异常。

如果在系统A和系统B中间加一个消息中间件,系统A就不用关心系统B是否出现故障了,因为那是系统B自己的事,等系统B故障恢复以后,就继续执行它自己的事,此时就对系统A没任何影响了。

为什么会有这样的效果呢?正式因为通过引入MQ,两个系统实现了异步化调用,也就实现了解耦,所以相互之间并没有任何影响。

5、流量削峰

假设系统A是不操作数据库的,因此只要多部署几台机器,就可以抗下每秒1万的请求,比如部署个20台机器,就可以轻松抗下每秒上万请求。

然后系统B是要操作一台数据库服务器的,那台数据库的上限是接收每秒6000请求,那么系统B无论部署多少台机器都没用,因为他依赖的数据库最多只能接收每秒6000请求。

如下图所示:

假设现在有1万的QPS请求到了系统A,由于系统A部署了20台机器,所以可以抗住1万QPS。然后系统A会瞬间把1万QPS转发给系统B,假设系统B也抗住了1万QPS,但是系统B对数据库发起了1万QPS的请求,数据库一定会瞬间被压垮。

所以这时如果引入MQ,就可以解决这个问题了。MQ这个技术抗高并发的能力远远高于数据库,同样的机器配置下,如果数据库可以抗每秒6000请求,MQ至少可以抗每秒几万请求。

为什么呢?因为数据库复杂啊,他要能够支持你执行复杂的SQL语句,支持事务等复杂的机制,支持你对数据进行增删改查,听着简单,其实是很复杂的!所以一般数据库单服务器也就支撑每秒几千的请求。

所以只要你引入一个MQ,那么就可以让系统A把每秒1万请求都作为消息直接发送到MQ里,MQ可以轻松抗下来这每秒1万请求。

接着,系统B只要慢慢的从MQ里获取消息然后执行数据库读写操作即可,这个获取消息的速度是系统B自己可以控制的,所以系统B完全可以用一个比较低的速率获取消息然后写入数据库,保证对数据库的QPS不要超过他的极限值6000。

这个时候因为系统A发送消息到MQ很快,系统B从MQ消费消息很慢,所以MQ里自然会积压一些消息,不过不要紧,MQ一般都是基于磁盘来存储消息的,所以适当积压一些消息是可以的。当系统A的高峰过去,每秒可能就恢复到1000 QPS了,此时系统b还是以每秒6000QPS的速度获取消息写入数据库,那么自然MQ里积压的消息就会慢慢被消化掉了。

所以这就是MQ进行流量削峰的效果,系统A发送过来的每秒1万请求是一个流量洪峰,然后MQ直接给扛下来了,都存储自己本地磁盘,这个过程就是流量削峰的过程,瞬间把一个洪峰给削下来了,让系统B后续慢慢获取消息来处理。

6、总结

消息中间件的主要作用就是削峰解耦,提升系统的响应速度。

1、了解消息中间件之前先了解一下什么是“同步”?

通常业务系统直接的调用如下图所示:

假设系统A收到了一个请求,可能是用户通过浏览器或者APP发起的,这时候系统A收到请求后马上去调用系统B,然后系统B再把返回结果返回给系统A,系统A才能返回给用户。如下图所示:

以上就是所谓的**“同步”**调用。这个同步的意思就是各个系统联动都是同步依次进行的,一个系统先动,然后立马带动另外一个系统一起动,最后大家依次干完活以后再返回结果。

2、如何依托消息中间件实现异步?

我们往系统A和系统B之间加入一个消息中间件,简称为“MQ”,也就是消息队列。

加入消息队列之后如何通信呢?

其实就是系统A执行完逻辑后给MQ中发送一条消息,然后就直接把结果返回给用户了。

(注:前提是系统A返回给用户的结果不依赖于系统B的返回结果。假设系统B为短信系统,系统A向MQ发送一条发送短信的消息指令,系统A并不关心短信是否立即发送,只要最终在有效的时间内发送成功就行了。)

如上图所示,系统B什么时候执行自己的任务呢?

这时候系统B根据自己的情况,可能是系统A投递消息到MQ之后的1秒内,也可能是1分钟之后,多长时间都有可能,不管多长时间,系统B肯定会从MQ里获取到一条属于自己的消息。

3、消息中间件到底有什么用?

假设系统A要调用系统B干一些事,然后系统A先执行一些操作,需要耗费20ms,接着系统B执行一些操作,需要200ms,所以总共需要220ms。如下图所示:

如果在系统A和系统中间加一个MQ呢?

系统A干完自己的事情耗时20ms,然后发一个消息到MQ耗时5ms,然后就直接返回结果给用户,总计耗时25ms。系统B从MQ中获取消息花费200ms和用户就没有关系了。所以用户只需等待25ms就收到结果了。如下图所示:

假设系统A调用系统B出现故障呢?因为系统A调用系统B肯定返回异常,此时系统A是不是也得返回异常给用户?而系统A是不是还要去处理这个异常?

这一切是因为系统A和系统B通过同步调用的模式耦合在一起,所以系统B一旦出现故障,很肯能影响系统A也有故障,而且系统A还得去关心系统B的故障,去处理对应的异常。

如果在系统A和系统B中间加一个消息中间件,系统A就不用关心系统B是否出现故障了,因为那是系统B自己的事,等系统B故障恢复以后,就继续执行它自己的事,此时就对系统A没任何影响了。

为什么会有这样的效果呢?正式因为通过引入MQ,两个系统实现了异步化调用,也就实现了解耦,所以相互之间并没有任何影响。

5、流量削峰

假设系统A是不操作数据库的,因此只要多部署几台机器,就可以抗下每秒1万的请求,比如部署个20台机器,就可以轻松抗下每秒上万请求。

然后系统B是要操作一台数据库服务器的,那台数据库的上限是接收每秒6000请求,那么系统B无论部署多少台机器都没用,因为他依赖的数据库最多只能接收每秒6000请求。

如下图所示:

假设现在有1万的QPS请求到了系统A,由于系统A部署了20台机器,所以可以抗住1万QPS。然后系统A会瞬间把1万QPS转发给系统B,假设系统B也抗住了1万QPS,但是系统B对数据库发起了1万QPS的请求,数据库一定会瞬间被压垮。

所以这时如果引入MQ,就可以解决这个问题了。MQ这个技术抗高并发的能力远远高于数据库,同样的机器配置下,如果数据库可以抗每秒6000请求,MQ至少可以抗每秒几万请求。

为什么呢?因为数据库复杂啊,他要能够支持你执行复杂的SQL语句,支持事务等复杂的机制,支持你对数据进行增删改查,听着简单,其实是很复杂的!所以一般数据库单服务器也就支撑每秒几千的请求。

所以只要你引入一个MQ,那么就可以让系统A把每秒1万请求都作为消息直接发送到MQ里,MQ可以轻松抗下来这每秒1万请求。

接着,系统B只要慢慢的从MQ里获取消息然后执行数据库读写操作即可,这个获取消息的速度是系统B自己可以控制的,所以系统B完全可以用一个比较低的速率获取消息然后写入数据库,保证对数据库的QPS不要超过他的极限值6000。

这个时候因为系统A发送消息到MQ很快,系统B从MQ消费消息很慢,所以MQ里自然会积压一些消息,不过不要紧,MQ一般都是基于磁盘来存储消息的,所以适当积压一些消息是可以的。当系统A的高峰过去,每秒可能就恢复到1000 QPS了,此时系统b还是以每秒6000QPS的速度获取消息写入数据库,那么自然MQ里积压的消息就会慢慢被消化掉了。

所以这就是MQ进行流量削峰的效果,系统A发送过来的每秒1万请求是一个流量洪峰,然后MQ直接给扛下来了,都存储自己本地磁盘,这个过程就是流量削峰的过程,瞬间把一个洪峰给削下来了,让系统B后续慢慢获取消息来处理。

6、总结

消息中间件的主要作用就是削峰解耦,提升系统的响应速度。