网上关于Apache Kafka的介绍已经有很多了,因此我不打算在这里对它的概念做过多的描述,更多的是从应用场景的角度来切入我们的Kafka学习之旅。
还记得我当初在做一个分布式系统的日志分析时,还是用log4j将多台机器的日志输出到flume,再由flume组件sink到一个指定目录文件中,然后再去对文件进行解析处理。这种方案解决了分布式系统的日志归并问题,但实时性欠佳,而且如果日志文件过大,解析起来也很耗时。那么有没有什么方案既能实现分布式服务日志的归并,还能提供实时处理能力呢?于是我们想到了Apache Kafka。
根据官网的描述,Apache Kafka能提供数据流的实时发布和订阅、实现消息分类、提供集群服务模式,这些特性能满足我们的业务需求。通过进一步研究,我们了解了更多细节。
Kafka可以对消息进行分类,将不同的消息划分为不同的topic,然后提供消息生成接口,即Producer API,发送指定topic的消息到kafka服务,同时也提供消息消费接口,即Consumer API,从kafka服务中接收和处理指定topic的消息。
这个过程我们可以通过下面的结构图来了解:
Kafka服务的消息数据存储很有特色,它有几个特点,我归纳了一下,主要包括:
1、消息分类。message消息按Topic(即主题类别)分类存储,方便Consumer按照Topic主题类别去读取消费。
2、消息分区与分段。同一个Topic下的消息可以保存在不同机器节点上(每个机器节点保存一个或多个分区partition),由Partition分区机制来实现,而同一个Partition分区上的数据文件是按segment(即分段)存储的,这两个特性保证了kafka的高并发性和高吞吐率。
3、多节点备份。同一Partition分区数据可以有多个节点备份(副本),由Replication机制来实现,保障服务的可靠性。一个Topic主题的消息读写都是在一个固定的副本上执行的,这个副本就是备份节点列表中的Leader主备份节点,其他Follow节点会从Leader主备份节点上拉取数据进行同步。
将上述三个特点表现在kafka的结构图里,我们可以看到:
一个Topic主题的消息,可以有三个partition分区,每条消息根据key值被分配到一个partition上进行存储。一个partition上的消息分不同的segment保存数据,当segment大小超过阈值时建立新的segmeng。
Kafka的消息消费过程由Consumer消费者来完成,每个消费者可以设置成归属于一个消费者群组(Consumer Group)。Kafka消息消费的过程也有几个特点:
1、若干个consumer实例可归并到一个consumer Group中。
2、topic主题中的每个消息message将会被传送给预定消息的consumer Group组中的某一个consumer;consumer实例可以是分布式程序或分布式机器。
3、如果所有consumer实例都在一个Group中,那就跟传统的队列一样,需在各个consumer之间进行负载均衡;
如果所有consumer实例分布在不同的Group中,那就跟发布-订阅模式一样,所有message消息会广播给所有consumer。
4、kafka只保证在一个partition分区中顺序取数据;在多个partition分区中取数据时,不能保证所有数据的顺序。
5、如果要保证全局数据的顺序,则只能有一个partition分区,那样的话就只能有一个consumer了。(partition一定不能比consumer少,consumer多了会闲置,浪费资源)
6、Kafka的客户端与服务器通信采用的是TCP协议。
7、一个message消息只能传输给某一个Group中的某一个consumer,即:一个Group中所有consumer共享一个offset标记位,所以一条message只能供一个Group中的一个consumer消费,之后可再被其他Group中的某一个consumer消费。(一个Group中的一次性消费)
另外,我们应该知道,要管理分布式集群中的机器,zookeeper是少不了的。zookeeper在Kafka分布式集群环境中的作用是管理集群节点,保证集群的高可用性。具体作用包括:zookeeper集群的leader选取、kafka集群的Controller选举、consumer的rebalance机制和kafka消息集群元数据信息存储等。
kafka集群的Controller选举,是为了选举出kafka集群的Leader。kafka集群中的所有节点会去zookeeper注册一个临时节点,(节点路径是/controller,存储数据是:{"version":1,"brokerid":3,"timestamp":"1524398923253"})。
注册成功的节点将作为Kafka集群的Controller,这个Controller用来为每个partition分区选择Leader,partition分区Leader保存集群中其他备份节点列表,并维持各个备份间的数据同步。
这几块我们在后面再详细介绍。