1、基本概念
需要了解producer,consumer,groupId,broker,topic,partition,segment的概念,如下图。
2、版本名
kafka_2.10-0.8.2.jar,2.10是指Scala版本,0.8.2是指kafka版本。
3、核心功能
Producer API允许程序发布数据流到一个到多个Kafka topic。
Consumer API允许程序订阅一个到多个topic,并且进行消费。
Streams API允许程序作为一个数据流处理,将一个或多个topic中输入的数据进行消费,并生产数据流到一个或多个topics中。
Connector API,可以通过Connector管理Kafka和另一个系统之间的数据复制,比如去捕获关系型数据库中的任意改变到一个表中。
4、topic介绍
topic(不同的业务数据,分流到不同的topic进行处理)
kafka对与zookeeper是强依赖的,是以zookeeper作为基础的,即使不做集群,也需要zk的支持。以下是kafka中必须要填写的配置文件,id为在zk中注册的brokerid,后者为要注册到的zookeeper的host和port。
broker.id=0 zookeeper.connect=localhost:2181
zk说白了,就是一个节点服务系统,至于用这个节点做什么,做单活、开关锁还是做检测服务器存活状态,都是业务代码根据这个节点做的一些逻辑处理。以下是kafka默认在zk中的节点层级结构:
5、partition介绍
partion可以看作一个有序的队列,里面的数据是储存在硬盘中的,追加式的。partition的作用就是提供分布式的扩展,一个topic可以有许多partions,多个partition可以并行处理数据,所以可以处理相当量的数据。只有partition的leader才会进行读写操作,folower仅进行复制,客户端是感知不到的。下图把kafka集群看成一个kakfa服务,仅显示leader。
1)offset概念
每一条数据都有一个offset,是每一条数据在该partition中的唯一标识。各个consumer控制和设置其在该partition下消费到offset位置,这样下次可以以该offset位置开始进行消费。
各个consumer的offset位置默认是在某一个broker当中的topic中保存的(为防止该broker宕掉无法获取offset信息,可以配置在每个broker中都进行保存,配置文件中配置)
offsets.topic.replication.factor=3 transaction.state.log.replication.factor=3 transaction.state.log.min.isr=3
2)replicas的同步时机。
假如有N个replicas,其中一个replica为leader,其他都为follower,leader处理partition的所有读写请求,于此同时,follower会被动定期的去复制leader上的数据。
3)ISR介绍
leader会追踪和维护ISR中所有follower的滞后状态。如果滞后太多(数量滞后和时间滞后两个维度,replica.lag.time.max.ms和replica.lag.max.message可配置),leader会把该replica从ISR中移除。被移除ISR的replica一直在追赶leader。如下图,leader写入数据后并不会commit,只有ISR列表中的所有folower同步之后才会commit,把滞后的follower移除ISR主要是避免写消息延迟。设置ISR主要是为了broker宕掉之后,重新选举partition的leader从ISR列表中选择。
滞后情况:新增副本,GC挂起,follower失效,I/O瓶颈。
6、producer介绍
send(String topic, Integer partition, Long timestamp, K key, V data)
producer在发送消息的时候,必须指定topic和data,可以选择指定partion、key、timestamp,其中时间戳有两种方式,CreateTime和LogAppendTime,前者是客户端设置时间,后者是broker在消息写入log时设置的时间。如果为null,用的是System.currentTimeMillis()。如果同时不指定partition和key,那么就用round-bin决定发送到哪个partition。
客户端会定时的取Broker的topic、partition、replicas等元数据信息,producer持有kafka节点的metadata信息,通过该信息创建ProducerPool,每次发送信息会根据要发送哪个Partition,来选择相应的Producer实例,Rpc连接。
7、consumer介绍
以下针对springBoot集成的kafka
@KafkaListener(topics = {"cache-music-user"},groupId="zwhUser",containerFactory = "batchAbleFactory") public void consumeBatch(List<ConsumerRecord<String,String>> recordList, Acknowledgment acknowledgment) throws InterruptedException { ... 方法体 ... }
consumer如何知道自己应该拉取哪一个partition。cordinator(某一个Kafka的broker)在分配consumer的时候,会选举consumer leader,后者分配每一个consumer要连接的broker,topic,partition,然后上报cordinator。然后consumer会根据自己被分配的partion去拉取数据。
批量读取和单数据读取,ack机制。
如果poll()时间超时,那么broker会认为consumer挂掉了,会踢掉该consumer。cordinator重新分配consumer。有时超时会抛异常,不过也会重新分配consumer。
consumer的groupId机制。对于一个groupId中的consumer来说,一个partition只能由一个consumer来消费。即不可能多个consumer消费1个partition。如下:
consumer可以在不同的机器中。
三、延伸
1、kafka重新选举
KafkaController的作用。Kafka集群中多个broker,有一个会被选举为controller leader,负责管理整个集群中分区和副本的状态,比如partition的leader 副本故障,由controller 负责为该partition重新选举新的leader 副本;当检测到ISR列表发生变化,有controller通知集群中所有broker更新其MetadataCache信息;或者增加某个topic分区的时候也会由controller管理分区的重新分配工作
KafkaController创建节点的方式去选举,作为leader,任何follower挂了,zk会感知到并通过Controller注册的Wather去通知Controller去重新选举。而leader挂了,zk会感知到,会通过Wather机制通知每一个broker去竞争Master。而ReplicaManager每个broker都有,是接受Contrloller的请求,对本服务上的partition进行管理的。
2、效率高的原因
因为kafka的数据都是存储在硬盘中,甚至有的公司将kafka其作为数据库使用,既然数据是基于硬盘的,那么为何kafka还是能够拥有如此高的吞吐量呢?
1)硬盘的索引功能。二分查找法。
分区:找到响应的分区
分段:根据文件segment的命名可以确认要查找的offset或timestamp在哪个文件中。
稀疏索引:快速确定要找的offset在哪个内存地址的附近。
2)I/O优化
普通程序I/O需要把Disk中的信息复制到系统环境内存(步骤1),再复制到kafka应用环境内存(步骤2),然后步骤3,步骤4到Socket通过网络发出,重复复制文本,I/O消耗大。
kafka则不一样:
3、kafka和rabbitMq的对比。
kafka是一种高吞吐量的分布式发布订阅消息系统。和rabbitMq各占半臂江山。以下是对比:
性能来说,kafka的吞吐量较大。kafka易于向外扩展,所有的producer、broker、consumer无需停机都可以即刻扩展机器。信息将全部的信息持久化到硬盘上,生产和消费互不影响,很灵活。功能来说,kafka适用于日志,事实上kafka本身就是LinkIn公司开发用于日志系统的,所以其文件叫做log。用户跟踪管道,对用户网页行为的记录跟踪,用于离线数据分析或者做报表。大数据分析。