主流消息中间件架构分析
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
主流消息中间件架构分析
Kafka
首先还是来看Kafka的系统架构(做消息中间件逃不开要去了解Kafka)。
Kafka ecosystem包含以下几块内容:
•Producer
•Consumer
•Kafka cluster
•ZooKeeper
其中ZooKeeper承当了NameServer的角色,同时用于保存系统的元数据,提供选主、协调等功能。
Broker是真正的服务端,用于存储消息。
可用性
首先看外部依赖的可用性。如果你的系统“强依赖”了外部的其他服务,那么你的系统的可用性必然和外部服务的可用性相关。(强依赖表示不可脱离依赖的服务保持正常运行)
从上面的架构可以看出Kafka只是依赖了ZooKeeper,而ZooKeeper本身是高可用的(2N+1个节点的ZK集群可以容忍N个节点故障),所以不会对整个集群的可用性造成影响。
接着看Kafka自身的可用性。谈可用性必然就会涉及到备份问题,没有备份就意味着存在单点问题,也就没有高可用可言了。所以我们具体来看一下Kafka的备份策略。
Kafka Replication的数据流如上图所示,从图中可以得到的一些信息:
1. 分区是有备份的,如topic1-part1上图中有3个
2. 分区的备份分布在不同的Broker上,上图中topic1-part1分布在broker1、broker2、broker3上,其中broker1上的为Leader
3. 分区的Leader是随机分布的,上图中topic1-part1的Leader在broker1,topic2-part1的Leader在Broker上,topic3-part1的Leader的Broker4上
4. 消息写入到Leader分区,之后通过Leader分区复制到Follower分区
Kafak这样的Replication策略,保证了任何一个Broker出现故障时,系统依旧是可用的。如broker1出现故障,此时会重新选举topic1-part1的Leader,之后可能是broker2或者broker3上的topic1-part1成为Leader然后负责消息的写入。
所以系统的可用性取决于分区备份的数量,这个备份数据是可配置的。
Kafka自身通过Replication实现了高可用,结合依赖的ZooKeeper也是高可用,所以整个系统的可用性得到了较好的保障。
可靠性
在消息中间件中,可靠性主要就是写入的消息一定会被消费到,条消息不会丢失。
在分布式环境中消息不丢失有两点:
1. 消息在成功写入一个节点后,消息会做持久化
2. 消息会被备份到其他物理节点
只要做到上面两点就可以保证除所有节点都发生永久性故障的情况下数据不会丢失。
Kafka Broker上写入的消息都会刷盘(可以是异步刷盘也可以是同步刷盘),也会备份到其他物理节点,所以满足以上两点。
异步刷盘结合多节点的备份策略也能提供比较好的可靠性,除非是机房掉电之类的情况导致所有节点未刷盘的数据丢失。
当然,消息丢失不一定指消息真的从磁盘上被销毁或者没被存储下来,如果消息被存储下来了,但是没办法被消费,对客户端来说也是消息丢失。比如Consumer收到消息后进行ACK之后再消费,如果在消费之前Crash了,那么下一次也不会拿到这条消息,也可以理解成消息丢了,但是这这篇文章中我们不讨论这种情况。
评价
优点
1. 部分功能托管给了ZK,自身只需要关注消息相关的内容,从这个角度上说是简化了部分
内容
2. 机器利用率高。从上面备份的策略可以看出不同Broker之间数据是互为备份的,这样的结构相对于主从模式提高了机器利用率(大部分主从模式,从都是无用状态的)
缺点
1. 引入了ZK,增加了外部依赖,增加了运维的复杂性
备份的方式从系统架构上说,互为主备是较好的方式,但是实现上会比较复杂,如果是自己去实现一个MQ,还是从主从的模式入手比较容易。
Kafka的备份策略及基层WAL的实现就比较复杂了,这个以后有机会说
RocketMQ
(图片取自RocketMQ_design文档)
RocketMQ中包含以下几块内容:
•Producer
•Consumer
•NameServer
•Broker
Producer及Consumer和Kafka相同(所有的MQ都会提供Producer和Consumer),Rocket也是有Broker集群,和Kafka最大的区别是RocketMQ自己实现了一个集群模式的NameServer服务。
可用性
RocketMQ的可用性也分为NameServer和Broker两块讨论。
NameServer是集群模式的,且“几乎”是无状态的,可以集群部署,所以不会存在可用性的问题。(无状态意味着每个节点是独立提供服务的,只需要部署多个节点就可以解决可用性的问题)
Broker的可用性又可以分为两块,对一个Topic而言,它可以分布在多个Master Broker上,这样在其中一个Broker不可用之后,其他的Broker依旧可以提供服务,不影响写入服务。在一个Master Broker挂掉之后虽然可以通过其他Master来保证写入的可用性,但是已经写入到故障Broker的部分数据可能会无法消费。RocketMQ通过Master-Slave的模式来解决这个问题。
Master永久故障后可以将Master上的读取请求转移到Slave上,这样可以保证系统的可用性(Master-Slave之间是异步复制的,意味着可能少量数据还没有从Master复制到Slave,这个在可靠性部分讨论)。
综合上面的两点,RocketMQ也提供了高可用的特性,且可用性只取决于自身的服务,没有像Kafka一样引入额外的,像ZK这样的服务。
可靠性
可靠性从单个Broker写入消息的可靠性和消息备份两个角度去考虑。
RocketMQ采用了同步刷盘的方式来持久化写入的消息。