什么是kafka?
kafka是一个分布式流式平台,能够通过订阅-发布模式在应用之间实时传递数据流,同时保证可靠性和容错性;简单理解,就是一个分布式消息队列。
kafka涉及的基本概念
- broker:即kafka进程实例,既可以以单点方式运行,也可以通过多个节点组成集群运行;
- record:kafka中的每条记录称为一个record,由key、value、timestamp 3个部分组成;
- topic:消息可以分类,每个类别称作一个topic,一个topic可以理解为一个逻辑上的消息队列;
- partition:一个topic所包含的数据可以通过"分区"存放到不同的物理机上或者存放到同一物理机的不同目录。引入partition表示topic在物理上的分区,对应文件系统的一个目录(存放分区对应的record和索引文件)。
- producer:产生消息的一组进程,负责将消息放入到broker;
- consumer:处理消息的一组进程,负责读取broker中的消息并执行业务处理;
- consumer group:用来指定同属一个组的consumer,同一组的consumer不能重复消费同一条消息,因为同一个group的consumer分别对接消费不同的partition;
kafka包含4个核心的API:
区别于上述基本概念,主要是用于提供编程的API:
- Producer API:用于编程实现producer逻辑,发布消息到一个或者多个topic;
- Consumer API:用于编程实现consumer逻辑,从一个或者多个topic中订阅并且处理消息;
- Stream API:将应用程序作为一个流式处理器,从topic中订阅消息、并进行处理,然后再发布到其它topic中;
- Connector API:用于负责对接broker和外部系统之间的数据读写操作,kafka已经提供很多现成的connector实现。可以帮助建立一个可以重用的Producer或者Consumer,比如:通过基于关系型数据库的connector可以在数据表中保存每次变更;基于文件系统的connector,可以实现broker与文件之间的数据传递;
对topic和partition的理解
- topic可以看做是对一系列消息的分类,producer会将相同类别的消息发送到同一个topic。一个topic可以被0个或者多个consumer订阅。
- 在kafka集群内部,一个topic的数据会存放到多个分区日志中,每个分区称为一个partition;
- 在一个partition中,消息序列是有序的(按照写入的时间顺序)、并且不可变的(消息提交,不可改变);partition中会为每条消息分配一个唯一的id,称作offset,用来唯一标识分区中的一条消息记录;
topic中消息的顺序并非全局有序,只是局部有序;
单看每个partition中的消息都是按照写入顺序排列的,但是从topic的视角来看,由于是并发处理多个partition中的消息,因而整个处理过程并非是有序的;
- kafka集群会保存所有已经发布的消息,无论消息是否被消费;可以配置保留消息的时长;kafka中性能随着数据量的增加是常数级下降,因而保留较长时间段的消息并不是问题;
- consumer处理消息的标识,由consumer自己维护,每个consumer中需要保留offset元数据,用于标识当前读取消息在日志中的位置;
消息读取进度由每个consumer通过改变offset自行控制;
consumer即可以按照顺序读取每一条消息,也可以改变offset到之前的位置,重复读取旧的消息;或者改变offset到之后的位置,用来跳过一部分消息;这种设计使得consumer的接入和断开变得非常容易,不会影响到集群中的其它consumer;
- partition的设计主要包含2个目的:扩容和并发。首先,一个topic可以包含多个partition,多个partition可以分布在多个机器上,因而可以处理大规模的数据;同时,多个partition可以同时被多个consumer消费,因而提高了并发性;
分布式概念的理解
- broker:一个kafka集群中的一个实例进程。一个topic的partition可以分布在集群中的多个broker;每个partition可以通过配置指定副本数量,每个副本(replication)存放在不同的broker上,以此进行容错;
- partition:每个partition的副本包含一个leader、0个或者多个follower。leader负责处理当前partition数据的所有读写请求,同时所有follower复制同步leader的数据;当leader所在的broker宕掉后,follower中的一个会自动变为新的leader;集群中的每个broker都可以看做是一部分partition的leader,同时又可以看做是其它partition的follower,因而保证了集群的负载均衡;
- producer:用于发布消息到多个topic的一组进程。可以选择消息发布在topic的那个partition上。即可以以轮询的方式将消息轮流放到每个partition上,以保证负载均衡。也可以通过定制分区策略来保证消息落到特定的分区;
- consumer:用于处理消息的一组进程或者多组进程。每组进程划分为一个group,对于同一个topic的一个group内,一条消息只会被一个consumer消费。一个group中的一个consumer负责消费一个topic中的一个或者多个partition,不同的consumer消费的partition不重合。该设计可以保证同一个group内消息的负载均衡,又可以保证消息不被同时消费。consumer和partition通过kafka协议动态维护,当新加入一个consumer,将会把其余consumer负责消费的partition分配给该consumer;相反,当有consumer宕机后,其负责的partition将会被分配给剩余的consumer。一个group中的consumer数量不应该比partition的数量多。
partition+group 保证按顺序读取消息
在一个group中,一个partition只会绑定给一个consumer进程消费,且一个partition中的消息是局部有序的。如果我们需要保障某一批消息按顺序执行,只要保障其能够落入同一个partition中即可(消息设置相同的key)。如果需要保证消息的全局顺序,则可以使topic仅包含一个partition,从而仅有一个consumer进行消费;
kafka的应用场景
- 消息队列
kafka用作message broker(消息代理),适用于高吞吐、内建分区、可复制、可容错的消息队列。 - 网站活动追踪
通过一系列实时的订阅-发布数据流,重建用户活动轨迹。将网站活动(PV,搜索等动作)发布到kafka的topic中,供下游实时处理,监控或者加载到线下数据仓库做离线计算和报表。 - 运行数据统计
用于监控运行数据,汇聚之后进行统计。 - 日志聚合
用于替代Flume、Scribe的等日志收集工具,提供高性能、持久性、低延迟的日志收集。 - 流式处理
用作流式处理工具,进行数据的聚合、富集、转换等操作。类似与Apache Storm等工具。 - 事件源模式实现
用于实现Event Sourcing Pattern